home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Sample Code / Sample Editors⁄Viewers / Picture Viewer / Source / PictureViewer.cpp < prev    next >
Encoding:
Text File  |  1995-12-08  |  138.9 KB  |  4,367 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2.     File:            PictureViewer.cpp
  3.     
  4.     Written by:        Sue Dumont        [based on SamplePart by Steve Smith]
  5.     
  6.     Copyright:        © 1994-95 by Apple Computer, Inc., all rights reserved.
  7.  
  8.     Description:    PictureViewer demonstrates the functionality of a
  9.                     viewer part.
  10.     
  11.     Demonstrates:     1. Open
  12.                      2. Adding A Display Frame
  13.                      3. Adding A Facet
  14.                      4. Part Drawing
  15.                      5. Refcounting Geometry
  16.                      6. ViewTypes & Presentations
  17.                      7. Display Frame 'ternalization
  18.                      8. Part Init & Externalization
  19.                      9. Part Init & partWrapper
  20.                     10. Part Storage Model
  21.                     11. Persistent Reference
  22.                     12. RefCounting
  23.                     13. Storage Unit
  24.                     14. Activation
  25.                     15. Basic Event Handling
  26.                     16. Menu Handling
  27.                     17. Windows & Dialogs
  28.                     18. Exception Handling
  29.                     19. Memory Manager
  30.                     20. Using Resources    
  31.                     21. Lazy Frame Internalization
  32.                     22. Writing/Fulfilling Promises
  33.     
  34.     Notes:        •    somThis is not set in methods where our internal data
  35.                     members are not accessed.
  36.     
  37.                 •    A viewer's stationery doesn't have any functionality.
  38.  
  39.                 •    Temp objects are automatically released when they go
  40.                     out of scope, so there's no need to release them.
  41. ------------------------------------------------------------------------------*/
  42.  
  43. // -- Compiler/Preprocessor Notification --
  44.  
  45. #ifndef _COMPILERDEFS_
  46. #include "CompDefs.h"
  47. #endif
  48.  
  49. // -- OpenDoc Utilities --
  50.  
  51. #ifndef _EXCEPT_
  52. // Exceptions define several important macros (eg. CHECKENV)
  53. // which are used in the SOM method dispatch glue. If Except.h
  54. // is not included early enough, exceptions may not be thrown
  55. // correctly when returning from a SOM method with the "ev" parameter set.
  56. #include <Except.h>
  57. #endif
  58.  
  59. // -- PictureViewer Includes
  60.  
  61. // Notification that this is a SOM source file
  62. #define SampleCode_PictureViewer_Class_Source
  63.  
  64. // define underscore (_) field names
  65. #define VARIABLE_MACROS
  66.  
  67. #ifndef _PICTUREVIEWERDEF_
  68. #include "PictureViewerDef.h"
  69. #endif
  70.  
  71. #ifndef _PICTUREVIEWERGLOBALS_
  72. #include "PictureViewerGlobals.h"
  73. #endif
  74.  
  75. #ifndef _PICTUREVIEWERUTILS_
  76. #include "PictureViewerUtils.h"
  77. #endif
  78.  
  79. #ifndef SOM_SampleCode_PictureViewer_xih
  80. #include "PictureViewer.xih"
  81. #endif
  82.  
  83. #ifndef _SAMPLECOLLECTIONS_
  84. #include "SampleCollections.h"
  85. #endif
  86.  
  87. // -- OpenDoc Includes --
  88.  
  89. #ifndef SOM_ODArbitrator_xh
  90. #include <Arbitrat.xh>
  91. #endif
  92.  
  93. #ifndef SOM_ODCanvas_xh
  94. #include <Canvas.xh>
  95. #endif
  96.  
  97. #ifndef SOM_ODClipboard_xh
  98. #include <Clipbd.xh>
  99. #endif
  100.  
  101. #ifndef SOM_Module_OpenDoc_Commands_defined
  102. #include <CmdDefs.xh>
  103. #endif
  104.  
  105. #ifndef SOM_ODDraft_xh
  106. #include <Draft.xh>
  107. #endif
  108.  
  109. #ifndef SOM_ODFacet_xh
  110. #include <Facet.xh>
  111. #endif
  112.  
  113. #ifndef SOM_ODFrameFacetIterator_xh
  114. #include <FrFaItr.xh>
  115. #endif
  116.  
  117. #ifndef SOM_Module_OpenDoc_Foci_defined
  118. #include <Foci.xh>
  119. #endif
  120.  
  121. #ifndef SOM_ODFocusSet_xh
  122. #include <FocusSet.xh>
  123. #endif
  124.  
  125. #ifndef SOM_ODMenuBar_xh
  126. #include <MenuBar.xh>
  127. #endif
  128.  
  129. #ifndef SOM_ODSession_xh
  130. #include <ODSessn.xh>
  131. #endif
  132.  
  133. #ifndef SOM_ODShape_xh
  134. #include <Shape.xh>
  135. #endif
  136.  
  137. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  138. #include <StdDefs.xh>
  139. #endif
  140.  
  141. #ifndef SOM_Module_OpenDoc_StdProps_defined
  142. #include <StdProps.xh>
  143. #endif
  144.  
  145. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  146. #include <StdTypes.xh>
  147. #endif
  148.  
  149. #ifndef SOM_ODStorageUnit_xh
  150. #include <StorageU.xh>
  151. #endif
  152.  
  153. #ifndef SOM_ODTranslation_xh
  154. #include <Translt.xh>
  155. #endif
  156.  
  157. #ifndef SOM_ODWindow_xh
  158. #include <Window.xh>
  159. #endif
  160.  
  161. #ifndef SOM_ODWindowState_xh
  162. #include <WinStat.xh>
  163. #endif
  164.  
  165.  
  166. // -- OpenDoc Utilities --
  167.  
  168. #ifndef _FOCUSLIB_
  169. #include <FocusLib.h>
  170. #endif
  171.  
  172. #ifndef _ISOSTR_
  173. #include <ISOStr.h>
  174. #endif
  175.  
  176. #ifndef _ITEXT_
  177. #include <IText.h>
  178. #endif
  179.  
  180. #ifndef _ODDEBUG_
  181. #include <ODDebug.h>
  182. #endif
  183.  
  184. #ifndef _ODMEMORY_
  185. #include <ODMemory.h>
  186. #endif
  187.  
  188. #ifndef _ODNEW_
  189. #include <ODNew.h>
  190. #endif
  191.  
  192. #ifndef _ODUTILS_
  193. #include <ODUtils.h>
  194. #endif 
  195.  
  196. #ifndef _STDTYPIO_
  197. #include <StdTypIO.h>
  198. #endif
  199.  
  200. #ifndef _STORUTIL_
  201. #include <StorUtil.h>
  202. #endif
  203.  
  204. #ifndef _TEMPOBJ_
  205. #include <TempObj.h>
  206. #endif
  207.  
  208. #ifndef _TEMPITER_
  209. #include <TempIter.h>
  210. #endif
  211.  
  212. #ifndef _USERSRCM_
  213. #include <UseRsrcM.h>
  214. #endif
  215.  
  216. // -- Macintosh Includes --
  217.  
  218. #ifndef __DIALOGS__
  219. #include <Dialogs.h>
  220. #endif
  221.  
  222. #ifndef __ERRORS__
  223. #include <Errors.h>
  224. #endif
  225.  
  226. #ifndef __GXMATH__
  227. #include <GXMath.h>
  228. #endif
  229.  
  230. #ifndef __ICONS__
  231. #include <Icons.h>                // NewIconSuite, PlotIconSuite, DisposeIconSuite
  232. #endif
  233.  
  234. #ifndef __QUICKDRAW__
  235. #include <Quickdraw.h>
  236. #endif
  237.  
  238. #ifndef __PICTUTILS__
  239. #include <PictUtils.h>
  240. #endif
  241.  
  242. #ifndef __RESOURCES__
  243. #include <Resources.h>
  244. #endif
  245.  
  246. #ifndef __TEXTUTILS__
  247. #include <TextUtils.h>
  248. #endif
  249.  
  250. #ifndef __TOOLUTILS__
  251. #include <ToolUtils.h>
  252. #endif
  253.  
  254.  
  255. #pragma segment PictureViewer
  256.  
  257.  
  258. //==============================================================================
  259. // PictureViewer
  260. //==============================================================================
  261.  
  262. //------------------------------------------------------------------------------
  263. // Method:        somInit
  264. // Origin:        SOMObject
  265. //
  266. // Description:    somInit and somUninit methods behave like C++ constructors 
  267. //                in that the inherited methods are called automatically. 
  268. //                There is no need to call the parent class' somInit or somUninit.
  269. //
  270. //                Also, instance variables need not be initialized to 0 or kODNULL
  271. //                since SOM guarantees that a newly constructed object is zeroed.
  272. // Warnings:    You are not allowed to throw an exception from this method.
  273. //------------------------------------------------------------------------------
  274. SOM_Scope    void
  275. SOMLINK        PictureViewer__somInit
  276.             (
  277.                 SampleCode_PictureViewer*    somSelf
  278.             )
  279. {
  280.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  281.     SampleCode_PictureViewerMethodDebug("PictureViewer","somInit");
  282.         
  283.     _fDisplayMode        = kCommandCrop;        // default display
  284.     _fReadOnlyStorage    = kODFalse;
  285. }
  286.  
  287. //------------------------------------------------------------------------------
  288. // Method:        somUninit
  289. // Origin:        SOMObject
  290. //
  291. // Description:    This is the SOM equivalent of a C++ clas destructor. In this
  292. //                routine you should clean up any class members which weren't
  293. //                taken care of in the ReleaseAll and Release methods.
  294. //
  295. // Warning:        You are not allowed to throw an exception from this method.
  296. //------------------------------------------------------------------------------
  297. SOM_Scope    void
  298. SOMLINK        PictureViewer__somUninit
  299.             (
  300.                 SampleCode_PictureViewer*    somSelf
  301.             )
  302. {
  303.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  304.     SampleCode_PictureViewerMethodDebug("PictureViewer","somUninit");
  305. }
  306.  
  307. //------------------------------------------------------------------------------
  308. // Method:        Release
  309. // Origin:        ODRefCountedObject
  310. //
  311. // Description:    This method is called each time an object releases the
  312. //                part. If the refcount falls to 0, the part should
  313. //                release the _fSelf part reference.
  314. //
  315. // Warning:        If the part releases any other object when the refcount falls
  316. //                to zero, it will need to override the Acquire method so that
  317. //                the object can be referenced again if the parts refcount should
  318. //                be incremented before it is deleted.
  319. //------------------------------------------------------------------------------
  320. SOM_Scope    void
  321. SOMLINK        PictureViewer__Release
  322.             (
  323.                 SampleCode_PictureViewer*    somSelf,
  324.                 Environment*                ev
  325.             )
  326. {
  327.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  328.     SampleCode_PictureViewerMethodDebug("PictureViewer","Release");
  329.  
  330.     SOM_TRY
  331.         SampleCode_PictureViewer_parent_ODPart_Release(somSelf, ev);
  332.  
  333.         if ( _fSelf->GetRefCount(ev) == 0 )
  334.             ODGetDraft(ev, _fSelf)->ReleasePart(ev, _fSelf);
  335.     SOM_CATCH_ALL
  336.     SOM_ENDTRY
  337. }
  338.  
  339. //------------------------------------------------------------------------------
  340. // Method:        ReleaseAll
  341. // Origin:        ODPersistentObject
  342. //
  343. // Description:    This method is called just prior to the part being
  344. //                deleted by the Draft. The part must release all
  345. //                references to all refcounted objects it has stored
  346. //                internally; not doing so, will cause an "invalid ref
  347. //                count" exception/error.
  348. //
  349. //                If any promises exist on the clipboard, it is the part's
  350. //                responsibility to fulfill them at this time.
  351. //------------------------------------------------------------------------------
  352. SOM_Scope    void
  353. SOMLINK        PictureViewer__ReleaseAll
  354.             (
  355.                 SampleCode_PictureViewer*    somSelf,
  356.                 Environment*                ev
  357.             )
  358. {
  359.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  360.     SampleCode_PictureViewerMethodDebug("PictureViewer","ReleaseAll");
  361.  
  362.     SOM_TRY
  363.         // If the last part instance using the globals is released,
  364.         // we need to clean up and delete the globals.
  365.         
  366.         if ( --gGlobalsUsageCount == 0 )
  367.         {
  368.             // Release the menubar.
  369.             ODReleaseObject(ev, gGlobals->fMenuBar);
  370.             
  371.             // Delete the objects stored in the globals struct.
  372.             ODDeleteObject(gGlobals->fUIFocusSet);
  373.             ODDisposePtr(gGlobals->fPictScrapKind);
  374.             ODDisposePtr(gGlobals->fPictFileKind);
  375.             ODDisposePtr(gGlobals->fAppleHFSFlavor);
  376.  
  377.             // Delete the globals struct.
  378.             ODDeleteObject(gGlobals);
  379.         }
  380.  
  381.         // Dispose of the picture handle.
  382.         if ( _fPicture )
  383.             ODDisposeHandle(_fPicture);
  384.  
  385.         if ( _fGWorld )
  386.         {
  387.             DisposeGWorld((GWorldPtr)_fGWorld);
  388.             _fGWorld = kODNULL;
  389.         }
  390.  
  391.         if ( _fDisplayFrames )
  392.         {
  393.             CListIterator fiter(_fDisplayFrames);
  394.             for ( CFrameProxy* proxy = (CFrameProxy*)fiter.First();
  395.                     fiter.IsNotComplete(); proxy = (CFrameProxy*)fiter.Next() )
  396.             {
  397.                 // Delete the proxy object and its contents. The frame's
  398.                 // refcount will be decremented in the proxy destructor.
  399.                 fiter.RemoveCurrent();
  400.                 delete proxy;
  401.             }
  402.         
  403.             // Delete the display frame collection.
  404.             ODDeleteObject(_fDisplayFrames);
  405.         }
  406.         
  407.         SampleCode_PictureViewer_parent_ODPart_ReleaseAll(somSelf, ev);
  408.             
  409.     SOM_CATCH_ALL
  410.         // If something goes wrong while we are cleaning up, we must
  411.         // let the Draft know because there may be some refcounted objects
  412.         // which did not get released. Not to mention, possible memory
  413.         // leaks.
  414.     SOM_ENDTRY
  415. }
  416.  
  417. //------------------------------------------------------------------------------
  418. // Method:        Purge
  419. // Origin:        ODObject
  420. //
  421. // Description:    This method is called when the draft runs out of
  422. //                memory or when a part is being deleted. The part
  423. //                should free up as much memory as possible.
  424. //
  425. //                The part determines which views are being used in
  426. //                its display frames. The resources for the unused view
  427. //                types are purged.
  428. //
  429. // Note:         The calculations in this routine determine the
  430. //                amount of memory a specific icon requires at a
  431. //                specified bit depth.
  432. //------------------------------------------------------------------------------
  433. SOM_Scope    ODSize
  434. SOMLINK        PictureViewer__Purge
  435.             (
  436.                 SampleCode_PictureViewer*    somSelf,
  437.                 Environment*                ev,
  438.                 ODSize                        size
  439.             )
  440. {
  441.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  442.     SampleCode_PictureViewerMethodDebug("PictureViewer","Purge");
  443.  
  444.     // Purge is called during the creation of stationery. However,
  445.     // we have not create our internal display frames list, so 
  446.     // trying to iterate over it would be futile.
  447.     if ( _fDisplayFrames == kODNULL )
  448.         return 0;
  449.     
  450.     ODSize         bytesFreed        = 0;
  451.     ODBoolean    usingThumbnail  = kODFalse;
  452.     
  453.     SOM_TRY
  454.         // Iterate over the frames we are displayed through and determine
  455.         // which view types are currently in use.
  456.         
  457.         CListIterator fiter(_fDisplayFrames);
  458.         for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  459.                 fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
  460.         {
  461.             // If the display frame is real (was connected or added),
  462.             // get its view type; otherwise, ignore it.
  463.             if ( proxy->FrameIsLoaded(ev) )
  464.             {
  465.                 ODTypeToken    frameView = proxy->GetFrame(ev)->GetViewType(ev);
  466.                 
  467.                 if ( frameView == gGlobals->fThumbnailView )
  468.                     usingThumbnail = kODTrue;
  469.                     
  470.                     // Release the frame reference, but don't get rid of the
  471.                     // proxy object because we're not done with the frame. If
  472.                     // all parts release their references the frame will be
  473.                     // purged from memory.
  474.                     proxy->Purge(ev);
  475.             }
  476.         }
  477.         
  478.         // Based on the usage of the supported view types, free up as much
  479.         // memory as possible.
  480.         
  481.         if ( !usingThumbnail && _fGWorld != kODNULL )
  482.         {
  483.             bytesFreed += (ODSize)sizeof(CGrafPort);
  484.             PixMapHandle pixMap = GetGWorldPixMap((GWorldPtr)_fGWorld);
  485.             bytesFreed += (ODSize)ODGetHandleSize((Handle)pixMap);
  486.     
  487.             DisposeGWorld((GWorldPtr)_fGWorld);
  488.             _fGWorld = kODNULL;
  489.         }
  490.     SOM_CATCH_ALL
  491.     SOM_ENDTRY
  492.     
  493.     return bytesFreed;
  494. }
  495.  
  496. //------------------------------------------------------------------------------
  497. // Method:        InitPart
  498. // Origin:        ODPart
  499. //
  500. // Description:    This method is called ONLY when new stationery is being
  501. //                created for the part. This method should write out all
  502. //                standard/default properties and values that the part
  503. //                expects to see.
  504. //
  505. // Warning:        It is not appropriate to require user interaction while
  506. //                stationery is being created. Do not present the user
  507. //                with error dialogs or splash screens.
  508. //------------------------------------------------------------------------------
  509. SOM_Scope    void
  510. SOMLINK        PictureViewer__InitPart
  511.             (
  512.                 SampleCode_PictureViewer*        somSelf,
  513.                 Environment*                    ev,
  514.                 ODStorageUnit*                    storageUnit,
  515.                 ODPart*                            partWrapper
  516.             )
  517. {
  518.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  519.     SampleCode_PictureViewerMethodDebug("PictureViewer","InitPart");
  520.     
  521.     SOM_TRY
  522.         // We must call the initialize method of our parent
  523.         // class to allow OpenDoc to annotate our part's storageUnit, to 
  524.         // set our refcount, and to change our "initialized" flag to true.
  525.         SampleCode_PictureViewer_parent_ODPart_InitPart(somSelf, ev, storageUnit, 
  526.                                                         partWrapper);
  527.  
  528.           // To allow editor swapping (translation) at runtime, OpenDoc requires
  529.         // that we pass in a "reference" to ourselves when interacting with the
  530.         // API (eg. WindowState::RegisterWindow(), Dispatcher::RegisterIdle, etc).
  531.         // The "partWrapper" passed to us here and in InitPartFromStorage is the
  532.         // "reference" OpenDoc is asking us to use.
  533.         _fSelf = partWrapper;
  534.             
  535.         // We are being created, either as part of generating stationery or
  536.         // by some editor instantiating the part, so the destination storage
  537.         // unit must be writeable.
  538.         _fReadOnlyStorage = kODFalse;
  539.         
  540.         // Call the common initialization code to get set up.
  541.         somSelf->Initialize(ev);
  542.  
  543.         // Since we have just been created, our state/content info has
  544.         // never been written out, so setting our "dirty" flag will
  545.         // give us a chance to do that.
  546.         somSelf->SetDirty(ev);
  547.     SOM_CATCH_ALL
  548.         // Clean up will occur in the destructor which will be called
  549.         // shortly after we return the error.
  550.     SOM_ENDTRY
  551. }
  552.  
  553. //------------------------------------------------------------------------------
  554. // Method:        InitPartFromStorage
  555. // Origin:        ODPart
  556. //
  557. // Description:    This method is called when a document/stationery is
  558. //                being opened or when the part is internalized by its
  559. //                containing part. The part should merely read in its
  560. //                saved state/content and initialize itself. The part
  561. //                 must not alter its storage unit; otherwise, the "Save"
  562. //                 menu item becomes enabled without the user actually
  563. //                having made a change to the document.
  564. //------------------------------------------------------------------------------
  565. SOM_Scope    void
  566. SOMLINK        PictureViewer__InitPartFromStorage
  567.             (
  568.                 SampleCode_PictureViewer*    somSelf,
  569.                 Environment*                ev,
  570.                 ODStorageUnit*                storageUnit,
  571.                 ODPart*                        partWrapper
  572.             )
  573. {
  574.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  575.     SampleCode_PictureViewerMethodDebug("PictureViewer","InitPartFromStorage");
  576.  
  577.     SOM_TRY
  578.         // Call the initialize method of our parent PersistentObject class to generate
  579.         // the appropriate time/date stamp on our part's storage unit.
  580.         SampleCode_PictureViewer_parent_ODPart_InitPartFromStorage(somSelf,
  581.                                                 ev, storageUnit, partWrapper);
  582.     
  583.         // To allow editor swapping (translation) at runtime, OpenDoc requires
  584.         // that we pass in a reference to ourselves when interacting with the
  585.         // API (eg. WindowState::RegisterWindow(), Dispatcher::RegisterIdle, etc).
  586.         // The "partWrapper" passed to us here and in InitPart is the
  587.         // "reference" OpenDoc is asking us to use.
  588.         _fSelf = partWrapper;
  589.             
  590.         // Are we being opened from a read-only draft? If so, we cannot
  591.         // write anything back out to our storage unit.
  592.         _fReadOnlyStorage = ( ODGetDraft(ev, storageUnit)->
  593.                                 GetPermissions(ev) < kODDPSharedWrite );
  594.  
  595.         // Call the common initialization code to get set up.
  596.         somSelf->Initialize(ev);
  597.  
  598.         // Read in the state the part was in when it was last Externalized.
  599.         // This allows the part to present the same environment the user
  600.         // had the part set up in the last time it was displayed.
  601.         somSelf->InternalizeStateInfo(ev, storageUnit);
  602.     
  603.         // Read in the contents for the part editor/viewer.
  604.         somSelf->InternalizeContent(ev, storageUnit, kODNULL);
  605.  
  606.     SOM_CATCH_ALL
  607.         // Clean up will occur in the destructor which will be called
  608.         // shortly after we return the error.
  609.     SOM_ENDTRY
  610. }
  611.  
  612. //------------------------------------------------------------------------------
  613. // Method:        Initialize
  614. // Origin:        PictureViewer
  615. //
  616. // Description:    This method is called during the internalization of the part
  617. //                from a document. Its purpose is to initialize all fields of
  618. //                the part and to convert ISO types to tokens for faster 
  619. //                comparisons throughout the code.
  620. //
  621. //                If an exception is thrown in this method, it wil be propogated
  622. //                back to OpenDoc which will call our ReleaseAll() method and the
  623. //                class destructor. All memory allocated here will be cleaned up
  624. //                in the ReleaseAll() method.
  625. //------------------------------------------------------------------------------
  626. SOM_Scope    void
  627. SOMLINK        PictureViewer__Initialize
  628.             (
  629.                 SampleCode_PictureViewer*    somSelf,
  630.                 Environment*                ev
  631.             )
  632. {
  633.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  634.     SampleCode_PictureViewerMethodDebug("PictureViewer","Initialize");
  635.  
  636.     SOM_TRY
  637.         ODStorageUnit* storageUnit = _fSelf->GetStorageUnit(ev);
  638.         
  639.         // Store a reference to the Session object.
  640.         _fSession = storageUnit->GetSession(ev);
  641.     
  642.         // Create a list to keep track of the frames we are being
  643.         // displayed in. Used for maintenance (ie., Purging memory).
  644.         _fDisplayFrames = new CList;
  645.         
  646.         // Check to see if we need to initialize our globals.
  647.         if ( gGlobalsUsageCount == 0 )
  648.         {    
  649.             // Create our globals space. We store the globals in a struct so
  650.             // that we can put them in temp mem. Otherwise, CFM loads the globals
  651.             // with the data fragment of a CFM library in the application heap.
  652.             gGlobals = new PictureViewerGlobals;
  653.     
  654.             somSelf->InitializeMenuBar(ev);
  655.             
  656.             // We tokenize the values here and store them for equivalence
  657.             // tests in the activation methods.
  658.             gGlobals->fSelectionFocus = _fSession->Tokenize(ev, kODSelectionFocus);
  659.             gGlobals->fClipboardFocus = _fSession->Tokenize(ev, kODClipboardFocus);
  660.             gGlobals->fMenuFocus = _fSession->Tokenize(ev, kODMenuFocus);
  661.             gGlobals->fModalFocus = _fSession->Tokenize(ev, kODModalFocus);
  662.     
  663.             // Tokenize our part's main presentation, the default presentation
  664.             // and the standard view types.
  665.             gGlobals->fMainPresentation    = _fSession->Tokenize(ev, kMainPresentation);
  666.     
  667.             gGlobals->fFrameView = _fSession->Tokenize(ev, kODViewAsFrame);
  668.             gGlobals->fLargeIconView = _fSession->Tokenize(ev, kODViewAsLargeIcon);
  669.             gGlobals->fSmallIconView = _fSession->Tokenize(ev, kODViewAsSmallIcon);
  670.             gGlobals->fThumbnailView = _fSession->Tokenize(ev, kODViewAsThumbnail);
  671.             
  672.             // This part supports PICT data files, so we must get the value type
  673.             // from OpenDoc. We do this through the Translation object.
  674.             gGlobals->fPictScrapKind = _fSession->GetTranslation(ev)->
  675.                             GetISOTypeFromPlatformType(ev, kPictureDataType, kODPlatformDataType);
  676.                             
  677.             gGlobals->fPictFileKind = _fSession->GetTranslation(ev)->
  678.                             GetISOTypeFromPlatformType(ev, kPictureDataType, kODPlatformFileType);
  679.             
  680.             gGlobals->fAppleHFSFlavor = _fSession->GetTranslation(ev)->
  681.                             GetISOTypeFromPlatformType(ev, flavorTypeHFS, kODPlatformDataType);
  682.             
  683.             // We will also package the menu and selection foci so
  684.             // that we can request the "set" at activation time.
  685.             gGlobals->fUIFocusSet = _fSession->GetArbitrator(ev)->CreateFocusSet(ev);
  686.             gGlobals->fUIFocusSet->Add(ev, gGlobals->fMenuFocus);
  687.             gGlobals->fUIFocusSet->Add(ev, gGlobals->fSelectionFocus);
  688.         
  689.             // Determine what Script/Language the part is localized for.
  690.             // This is important/necessary for creating OpenDoc's text objects.
  691.             GetEditorScriptLanguage(ev, &gGlobals->fEditorScript, 
  692.                                                 &gGlobals->fEditorLanguage);        
  693.             
  694.             // The first client of the global variables is running.
  695.             gGlobalsUsageCount = 1;
  696.         }
  697.         else
  698.         {
  699.             // If the globals have been initialized, we just bump the "usage"
  700.             // count so that we know how many part instances are using them.
  701.             gGlobalsUsageCount++;
  702.         }
  703.     SOM_CATCH_ALL
  704.     SOM_ENDTRY
  705. }
  706.  
  707. //------------------------------------------------------------------------------
  708. // Method:        InitializeMenuBar
  709. // Origin:        PictureViewer
  710. //
  711. // Description:    This method is called during the initialization process and
  712. //                when the menubar object becomes invalid.
  713. //------------------------------------------------------------------------------
  714. SOM_Scope    void
  715. SOMLINK        PictureViewer__InitializeMenuBar
  716.             (
  717.                 SampleCode_PictureViewer*    somSelf,
  718.                 Environment*                ev
  719.             )
  720. {
  721.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  722.     SampleCode_PictureViewerMethodDebug("PictureViewer","InitializeMenuBar");
  723.  
  724.     SOM_TRY
  725.         // Clean up the menubar object if it already exists.
  726.         if ( gGlobals->fMenuBar )
  727.             ODReleaseObject(ev, gGlobals->fMenuBar);
  728.  
  729.         // It is required that parts instantiate their menubars from the base
  730.         // OpenDoc menu bar. This maintains consistency in the default menu
  731.         // items and their placement. Since the object is a copy, we can add
  732.         // and subtract menus and items without affecting other running parts.
  733.         gGlobals->fMenuBar = _fSession->GetWindowState(ev)->CopyBaseMenuBar(ev);    
  734.  
  735.         CUsingLibraryResources res;
  736.         
  737.         // Add Display menu for Crop and Scale commands.
  738.         gGlobals->fMenuBar->AddMenuLast(ev, kDisplayMenuID, 
  739.                                         GetMenu(kDisplayMenuID), _fSelf);
  740.         
  741.         // Register the Display menu commands. Crop is the first menuitem,
  742.         // and Scale is the second menuitem.
  743.         gGlobals->fMenuBar->RegisterCommand(ev, kCommandCrop, kDisplayMenuID, 1);
  744.         gGlobals->fMenuBar->RegisterCommand(ev, kCommandScale, kDisplayMenuID, 2);
  745.     SOM_CATCH_ALL
  746.     SOM_ENDTRY    
  747. }
  748.  
  749. //------------------------------------------------------------------------------
  750. // Method:        InternalizeStateInfo
  751. // Origin:        PictureViewer
  752. //
  753. // Description:    This method reads in state information. This is information
  754. //                related to the workings of the part editor, not the content.
  755. //
  756. //                The part writes out a list of weak references to its display
  757. //                frames. This allows the part to reuse the same display frames
  758. //                each time the document is opened. Those references are read
  759. //                back in and validated here.
  760. //
  761. // Note:        The StorageUnit interface requires the use of the ODByteArray
  762. //                struct. Look in StorUtil.h/cpp for an example of using the 
  763. //                ODByteArray struct.
  764. //------------------------------------------------------------------------------
  765. SOM_Scope    void
  766. SOMLINK        PictureViewer__InternalizeStateInfo
  767.             (
  768.                 SampleCode_PictureViewer*    somSelf,
  769.                 Environment*                ev,
  770.                 ODStorageUnit*                storageUnit
  771.             )
  772. {
  773.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  774.     SampleCode_PictureViewerMethodDebug("PictureViewer","InternalizeStateInfo");
  775.     
  776.     TRY
  777.         ODStorageUnitRef    weakRef;
  778.         ODULong                size;
  779.  
  780.         // Internalize the part's display frame list.
  781.         if ( storageUnit->Exists(ev, kODPropDisplayFrames, kODWeakStorageUnitRefs, 0) )
  782.         {
  783.             storageUnit->Focus(ev, kODPropDisplayFrames, kODPosUndefined,
  784.                                         kODWeakStorageUnitRefs, 0, kODPosUndefined);
  785.                                         
  786.             size = storageUnit->GetSize(ev);
  787.             storageUnit->SetOffset(ev, 0);
  788.         
  789.             for (ODULong offset = 0; offset < size; offset += kODStorageUnitRefSize)
  790.             {    
  791.                 TRY    
  792.                     StorageUnitGetValue(storageUnit, ev, kODStorageUnitRefSize,
  793.                                             (ODPtr)&weakRef);
  794.                 
  795.                     if ( storageUnit->IsValidStorageUnitRef(ev, weakRef) )
  796.                     {        
  797.                         // We lazily internalize our display frames, meaning we don't get
  798.                         // the frame until we absolutely need it. This reduces the time
  799.                         // to internalize the part and the amount of memory needed.
  800.                         
  801.                         // Convert the reference into a runtime id.
  802.                         ODID frameID = storageUnit->GetIDFromStorageUnitRef(ev, weakRef);
  803.         
  804.                         // Create a proxy class to support the lazy internalization.
  805.                         CFrameProxy* proxy = new CFrameProxy;
  806.                         proxy->InitFrameProxy(frameID, ODGetDraft(ev, storageUnit));
  807.         
  808.                         // Add the proxy to the display frame collection.
  809.                         _fDisplayFrames->Add(proxy);
  810.                     }
  811.                 CATCH_ALL
  812.                     // consume exception
  813.                 ENDTRY
  814.             }
  815.         }
  816.         
  817.         // Internalize the display mode setting
  818.         if ( storageUnit->Exists(ev, kPropDisplayMode, kODSLong, 0) )
  819.             _fDisplayMode = ODGetSLongProp(ev, storageUnit, kPropDisplayMode, kODSLong);
  820.     CATCH_ALL
  821.         // consume the exception, so don't set the ev parameter
  822.     ENDTRY
  823. }
  824.  
  825. //------------------------------------------------------------------------------
  826. // Method:        InternalizeContent
  827. // Origin:        PictureViewer
  828. //
  829. // Description:    This method is called during interalization of the
  830. //                part. The content of the part should be read in.
  831. //
  832. //                The part should look for content properties in the order of
  833. //                highest to lowest fidelity. This ensures the most accurate
  834. //                reproduction of the internalized content.
  835. //------------------------------------------------------------------------------
  836. SOM_Scope    void
  837. SOMLINK        PictureViewer__InternalizeContent
  838.             (
  839.                 SampleCode_PictureViewer*        somSelf,
  840.                 Environment*                    ev,
  841.                 ODStorageUnit*                    storageUnit,
  842.                 ODFacet*                        facet
  843.             )
  844. {
  845.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  846.     SampleCode_PictureViewerMethodDebug("PictureViewer","InternalizeContent");
  847.  
  848.     ODULong        size;
  849.     
  850.     SOM_TRY
  851.         if ( storageUnit->Exists(ev, kODPropContents, gGlobals->fPictScrapKind, 0) )
  852.         {
  853.             // Check for the Macintosh PICT scrap type.
  854.             storageUnit->Focus(ev, kODPropContents,
  855.                                 kODPosUndefined,
  856.                                 gGlobals->fPictScrapKind,
  857.                                 0,
  858.                                 kODPosUndefined);
  859.             
  860.             size = storageUnit->GetSize(ev);
  861.             
  862.             TRY
  863.                 if ( size > 0 )
  864.                 {
  865.                     // Allocate memory for the new picture data. If we are
  866.                     // successful, dispose of any old data and assign
  867.                     // the new storage to our part.
  868.                     ODHandle tempPict = ODNewHandle(size);
  869.     
  870.                     TempODHandleLock hLock(tempPict);
  871.                     StorageUnitGetValue(storageUnit, ev, size, *hLock);
  872.                     
  873.                     if ( _fPicture )
  874.                         ODDisposeHandle(_fPicture);
  875.                     _fPicture = tempPict;
  876.                 }
  877.             CATCH_ALL
  878.             ENDTRY
  879.         }
  880.         else if ( ODSUExistsThenFocus(ev, storageUnit, kODPropContents, gGlobals->fAppleHFSFlavor) )
  881.         {
  882.             size = storageUnit->GetSize(ev);
  883.         
  884.             if ( size > 0 )
  885.             {
  886.                 HFSFlavor* hfsInfo = (HFSFlavor*) ODNewPtrClear(size);
  887.                 
  888.                 // Assign the pointer to a temp mem pointer so that the memory block
  889.                 // will be automatically disposed of when it goes out of scope or in 
  890.                 // case an exception occurs.
  891.                 // is thrown. 
  892.                 TempODPtr autoDisposer = (ODPtr)hfsInfo;
  893.             
  894.                 StorageUnitGetValue(storageUnit, ev, size, hfsInfo);
  895.             
  896.                 if ( hfsInfo->fileType == kPictureDataType )
  897.                 {
  898.                     // PICT data exists, so read it in.
  899.                     somSelf->ReadPictureFile(ev, facet, hfsInfo, size);
  900.  
  901.                     TRY
  902.                         // Write out our preferred kind.
  903.                         ODSetISOStrProp(ev, storageUnit, kODPropPreferredKind, 
  904.                                                 kODISOStr, gGlobals->fPictScrapKind);
  905.                     CATCH_ALL
  906.                         // Remove the property and value if something went wrong.
  907.                         ODSURemoveProperty(ev, storageUnit, kODPropPreferredKind);
  908.                     ENDTRY
  909.                     
  910.                     // Call SetDirty so our content will be externalized.
  911.                     somSelf->SetDirty(ev);
  912.                 }
  913.             }
  914.         }
  915.     SOM_CATCH_ALL
  916.     SOM_ENDTRY
  917. }
  918.  
  919. //------------------------------------------------------------------------------
  920. // Method:        Externalize
  921. // Origin:        ODPersistentObject
  922. //
  923. // Description:    Write out the state information (display frames)
  924. //                to persistent storage. Also, be sure to call the
  925. //                parent class because one or more of its parent classes 
  926. //                may contain implementation.
  927. //------------------------------------------------------------------------------
  928. SOM_Scope    void
  929. SOMLINK        PictureViewer__Externalize
  930.             (
  931.                 SampleCode_PictureViewer*        somSelf,
  932.                 Environment*                    ev
  933.             )
  934. {
  935.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  936.     SampleCode_PictureViewerMethodDebug("PictureViewer","Externalize");
  937.     
  938.     // Ask our parent classes to externalize themselves.
  939.     SampleCode_PictureViewer_parent_ODPart_Externalize(somSelf, ev);
  940.  
  941.     SOM_TRY
  942.         if ( _fDirty && !_fReadOnlyStorage )
  943.         {
  944.             // Get our storage unit.
  945.             ODStorageUnit* storageUnit = _fSelf->GetStorageUnit(ev);
  946.             
  947.             // Verify that the storage unit has the appropriate properties
  948.             // and values to allow us to run. If not, add them.
  949.             somSelf->CheckAndAddProperties(ev, storageUnit);
  950.         
  951.             // Verify that there are no "bogus" values in the Content
  952.             // property.
  953.             somSelf->CleanseContentProperty(ev, storageUnit);
  954.             
  955.             // Write out the content data.
  956.             somSelf->ExternalizeContent(ev, storageUnit, kODNULLKey, kODNULL);
  957.             
  958.             // Write out the part's state information.
  959.             somSelf->ExternalizeStateInfo(ev, storageUnit, kODNULLKey, kODNULL);
  960.             
  961.             // Flag our part as no longer being dirty.
  962.             _fDirty = kODFalse;
  963.         }
  964.     SOM_CATCH_ALL
  965.         // Alert the user of the problem.
  966.         somSelf->HandleDialogBox(ev, kODNULL, kErrorBoxID, kErrExternalizeFailed);
  967.         // Change the error code value so the DocShell doesn't
  968.         // display an error dialog.
  969.         SetErrorCode(kODErrAlreadyNotified);
  970.     SOM_ENDTRY
  971. }
  972.  
  973. //------------------------------------------------------------------------------
  974. // Method:        ExternalizeStateInfo
  975. // Origin:        PictureViewer
  976. //
  977. // Description:    This method is called during externalization of the part.
  978. //                The current state of the part should be written out. This 
  979. //                state information may be lost during Data Interchange
  980. //                operations, so the part needs to recover gracefully if 
  981. //                information is missing or incomplete.
  982. //
  983. // Note:        The function StorageUnitSetValue is a macro which simplifies
  984. //                the use of ODByteArrary, which is required by the StorageUnit
  985. //                interface. Look in StorUtil.h/cpp for an example of using the
  986. //                ODByteArray struct.
  987. //------------------------------------------------------------------------------
  988. SOM_Scope    void
  989. SOMLINK        PictureViewer__ExternalizeStateInfo
  990.              (
  991.                  SampleCode_PictureViewer*        somSelf,
  992.                  Environment*                    ev,
  993.                  ODStorageUnit*                    storageUnit,
  994.                  ODDraftKey                        key,
  995.                  ODFrame*                        scopeFrame
  996.             )
  997. {
  998.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  999.     SampleCode_PictureViewerMethodDebug("PictureViewer","ExternalizeStateInfo");
  1000.  
  1001.     ODStorageUnitRef    weakRef;
  1002.     ODID                frameID;
  1003.     ODID                scopeFrameID;
  1004.     ODDraft*            fromDraft;
  1005.  
  1006.     SOM_TRY
  1007.         scopeFrameID = (scopeFrame ? scopeFrame->GetID(ev) : kODNULLID );
  1008.         fromDraft = ODGetDraft(ev, _fSelf);
  1009.         
  1010.         // Externalize the part's display frame list.
  1011.         storageUnit->Focus(ev, kODPropDisplayFrames, kODPosUndefined,
  1012.                                     kODWeakStorageUnitRefs, 0, kODPosUndefined);
  1013.         
  1014.         // Persistent object references are stored in a side table, rather than
  1015.         // in the property/value stream. Thus, deleting the contents of a value
  1016.         // will not delete the references previously written to that value. To
  1017.         // completely delete all references written to the value, we must
  1018.         // remove the value and add it back.
  1019.         storageUnit->Remove(ev);
  1020.         storageUnit->AddValue(ev, kODWeakStorageUnitRefs);
  1021.     
  1022.         CListIterator fiter(_fDisplayFrames);
  1023.         for ( CFrameProxy* proxy = (CFrameProxy*)fiter.First();
  1024.                 fiter.IsNotComplete(); proxy = (CFrameProxy*)fiter.Next() )
  1025.         {
  1026.             TRY
  1027.                 // Get the ID of the frame we are going to weakly reference.
  1028.                 frameID = proxy->GetID();
  1029.                     
  1030.                 // If a draft key exists, then we are being cloned to another draft.
  1031.                 // We must "weak" clone our display frame and reference the cloned
  1032.                 // frame. The part re-uses the frameID variable so there aren't two
  1033.                 // different GetWeakStorageUnitRef calls.
  1034.                 if ( key )
  1035.                     frameID = fromDraft->WeakClone(ev, key, frameID, kODNULLID, scopeFrameID);
  1036.                     
  1037.                 // Write out weak references to each of the part's display frames.
  1038.                 storageUnit->GetWeakStorageUnitRef(ev, frameID, weakRef);
  1039.                 StorageUnitSetValue(storageUnit, ev, kODStorageUnitRefSize, (ODPtr)&weakRef);
  1040.             CATCH_ALL
  1041.                 // consume the exception, so don't set ev parameter
  1042.             ENDTRY
  1043.         }
  1044.         
  1045.         // Externalize the display mode
  1046.         ODSetSLongProp(ev, storageUnit, kPropDisplayMode, kODSLong, _fDisplayMode);
  1047.     SOM_CATCH_ALL
  1048.     SOM_ENDTRY
  1049. }
  1050.  
  1051. //------------------------------------------------------------------------------
  1052. // Method:        ExternalizeContent 
  1053. // Origin:        PictureViewer
  1054. //
  1055. // Description:    This method is called during exteralization of the
  1056. //                part. The content of the part should be written out.
  1057. //------------------------------------------------------------------------------
  1058. SOM_Scope    void
  1059. SOMLINK        PictureViewer__ExternalizeContent
  1060.             (
  1061.                 SampleCode_PictureViewer*    somSelf,
  1062.                 Environment*                ev,
  1063.                 ODStorageUnit*                 storageUnit,
  1064.                 ODDraftKey                     key,
  1065.                 ODFrame*                    scopeFrame
  1066.             )
  1067. {
  1068.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  1069.     SampleCode_PictureViewerMethodDebug("PictureViewer","ExternalizeContent");
  1070.  
  1071.     SOM_TRY
  1072.         // Focus to our content property.
  1073.         storageUnit->Focus(ev, kODPropContents, kODPosUndefined,
  1074.                             gGlobals->fPictScrapKind, 0, kODPosUndefined);
  1075.     
  1076.         ODULong oldSize = storageUnit->GetSize(ev);
  1077.         
  1078.         if ( _fPicture )
  1079.         {            
  1080.             ODULong pictSize = ODGetHandleSize(_fPicture);
  1081.             
  1082.             // Write out the data. Use temp mem for the handle lock.
  1083.             TempODHandleLock hLock(_fPicture);
  1084.             StorageUnitSetValue(storageUnit, ev, pictSize, *hLock);
  1085.             
  1086.             // Delete the extra bytes in the value.
  1087.             if ( oldSize > pictSize )
  1088.                 storageUnit->DeleteValue(ev, (oldSize - pictSize));
  1089.         }
  1090.         else
  1091.         {
  1092.             // If we don't have content data, but data exists in the
  1093.             // storage unit, delete it.
  1094.             if ( oldSize > 0 )
  1095.                 storageUnit->DeleteValue(ev, oldSize);
  1096.         }
  1097.     SOM_CATCH_ALL
  1098.     SOM_ENDTRY
  1099. }
  1100.  
  1101. //------------------------------------------------------------------------------
  1102. // Method:        ExternalizeKinds
  1103. // Origin:        ODPart
  1104. //
  1105. // Description:    This method is called when the user wants to save the document
  1106. //                with multiple representations of the data. This is especially
  1107. //                useful for increasing the portability of documents cross-platform.
  1108. //
  1109. //                A part should verify that each kind is valid; that it exists in
  1110. //                the content property in the correct order; and then write the data.
  1111. //------------------------------------------------------------------------------
  1112. SOM_Scope    void
  1113. SOMLINK        PictureViewer__ExternalizeKinds
  1114.             (
  1115.                 SampleCode_PictureViewer*    somSelf,
  1116.                 Environment*                ev,
  1117.                 ODTypeList*                    kindset
  1118.             )
  1119. {
  1120.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  1121.     SampleCode_PictureViewerMethodDebug("PictureViewer","ExternalizeKinds");
  1122.  
  1123.     SOM_TRY
  1124.         if ( !_fReadOnlyStorage )
  1125.         {
  1126.             // Get our storage unit.
  1127.             ODStorageUnit* storageUnit = _fSelf->GetStorageUnit(ev);
  1128.             
  1129.             // Verify that the storage unit has the appropriate properties
  1130.             // and values to allow us to run. If not, add them.
  1131.             somSelf->CheckAndAddProperties(ev, storageUnit);
  1132.         
  1133.             // Verify that there are no "bogus" values in the Content property.
  1134.             somSelf->CleanseContentProperty(ev, storageUnit);
  1135.         
  1136.             // Write out the part's state information.
  1137.             somSelf->ExternalizeStateInfo(ev, storageUnit, kODNULLKey, kODNULL);
  1138.     
  1139.             // Even if the kindset contains no types we support, we must at least
  1140.             // write out our preferred (and only) kind.
  1141.             somSelf->ExternalizeContent(ev, storageUnit, kODNULLKey, kODNULL);
  1142.         }
  1143.     SOM_CATCH_ALL
  1144.     SOM_ENDTRY
  1145. }
  1146.  
  1147. //------------------------------------------------------------------------------
  1148. // Method:        ChangeKind
  1149. // Origin:        ODPart
  1150. //
  1151. // Description:    This method is called when the user changes the part's primary
  1152. //                kind and/or when the part editor is switched via the Info dialog.
  1153. //                Don't write the properties/values/data until Externalize is called.
  1154. //------------------------------------------------------------------------------
  1155. SOM_Scope    void
  1156. SOMLINK        PictureViewer__ChangeKind
  1157.             (
  1158.                 SampleCode_PictureViewer*        somSelf,
  1159.                 Environment*                    ev,
  1160.                 ODType                             kind
  1161.             )
  1162. {
  1163.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  1164.     SampleCode_PictureViewerMethodDebug("PictureViewer","ChangeKind");
  1165.  
  1166.     SOM_TRY    
  1167.         // PictureViewer has only one kind, but we need to make sure the
  1168.         // "Preferred Kind" property has the correct value. Check for
  1169.         // both the scrap kind and file kind, but only write out our
  1170.         // scrap kind.
  1171.         if ( ODISOStrEqual(kind, gGlobals->fPictScrapKind) ||
  1172.                 ODISOStrEqual(kind, gGlobals->fPictFileKind) )
  1173.         {
  1174.             // Get our storage unit.
  1175.             ODStorageUnit* storageUnit = _fSelf->GetStorageUnit(ev);
  1176.             
  1177.             TRY
  1178.                 // Write out the user's preferred kind.
  1179.                 ODSetISOStrProp(ev, storageUnit, kODPropPreferredKind, 
  1180.                                         kODISOStr, gGlobals->fPictScrapKind);
  1181.  
  1182.                 // Changing our kind dirties our content.
  1183.                 somSelf->SetDirty(ev);
  1184.             
  1185.                 // Immediately externalize ourselves in the "new" format.
  1186.                 somSelf->Externalize(ev);
  1187.             CATCH_ALL
  1188.                 // Remove the property and value if something went wrong.
  1189.                 ODSURemoveProperty(ev, storageUnit, kODPropPreferredKind);
  1190.             ENDTRY
  1191.         }
  1192.         else
  1193.             THROW(kODErrInvalidValueType);
  1194.     SOM_CATCH_ALL
  1195.     SOM_ENDTRY
  1196.  
  1197. }
  1198.  
  1199. //------------------------------------------------------------------------------
  1200. // Method:        CleanseContentProperty
  1201. // Origin:        PictureViewer
  1202. //
  1203. // Description:    This method is called during exteralization of the
  1204. //                part. The part should remove any value in the content
  1205. //                property that it cannot accurately write to.
  1206. //------------------------------------------------------------------------------
  1207. SOM_Scope    void
  1208. SOMLINK        PictureViewer__CleanseContentProperty
  1209.             (
  1210.                 SampleCode_PictureViewer*        somSelf,
  1211.                 Environment*                    ev,
  1212.                 ODStorageUnit*                    storageUnit
  1213.             )
  1214. {
  1215.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  1216.     SampleCode_PictureViewerMethodDebug("PictureViewer","CleanseContentProperty");
  1217.  
  1218.     ODULong numValues;
  1219.     ODULong index;
  1220.     
  1221.     SOM_TRY
  1222.         storageUnit->Focus(ev, kODPropContents, kODPosUndefined, 
  1223.                                 kODNULL, 0, kODPosAll);
  1224.         
  1225.         numValues = storageUnit->CountValues(ev);
  1226.         
  1227.         for ( index = numValues; index >= 1; index-- )
  1228.         {
  1229.             // Index from 1 to n through the values.
  1230.             storageUnit->Focus(ev, kODPropContents, kODPosUndefined, 
  1231.                                     kODNULL, index, kODPosUndefined);
  1232.     
  1233.             // Get the ISO type name for the value. The temp object
  1234.             // will automatically delete the returned value when this
  1235.             // scope is exited.
  1236.             TempODValueType value = storageUnit->GetType(ev);
  1237.             
  1238.             // If the value type is not one we support, remove it.
  1239.             if ( !ODISOStrEqual(value, gGlobals->fPictScrapKind) )
  1240.                 storageUnit->Remove(ev);
  1241.         }
  1242.     SOM_CATCH_ALL
  1243.     SOM_ENDTRY
  1244. }
  1245.  
  1246. //------------------------------------------------------------------------------
  1247. // Method:        UpdateFrame
  1248. // Origin:        PictureViewer
  1249. //
  1250. // Description:    Update the correct shape for the given frame.
  1251. //------------------------------------------------------------------------------
  1252. SOM_Scope    void
  1253. SOMLINK        PictureViewer__UpdateFrame
  1254.             (
  1255.                 SampleCode_PictureViewer*    somSelf,
  1256.                 Environment*                ev,
  1257.                 ODFrame*                    frame,
  1258.                 ODTypeToken                    view,
  1259.                 ODShape*                    usedShape
  1260.             )
  1261. {
  1262.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  1263.     SampleCode_PictureViewerMethodDebug("PictureViewer","UpdateFrame");
  1264.  
  1265.     TRY
  1266.         // Update the frame to have the new view and usedShape.
  1267.         
  1268.         // Invalidate the old used shape.
  1269.         frame->Invalidate(ev, kODNULL, kODNULL);
  1270.         
  1271.         frame->SetViewType(ev, view);
  1272.         frame->ChangeUsedShape(ev, usedShape, kODNULL);
  1273.         
  1274.         // Invalidate the new used shape.
  1275.         frame->Invalidate(ev, kODNULL, kODNULL);
  1276.     CATCH_ALL
  1277.         // Failing isn't great, but we can live with it, so don't set ev.
  1278.     ENDTRY
  1279. }
  1280.  
  1281. //------------------------------------------------------------------------------
  1282. // Method:        CalculateUsedShape
  1283. // Origin:        PictureViewer
  1284. //
  1285. // Description:    This method is called in response to one of the display 
  1286. //                frame's view being changed. The method calculates the 
  1287. //                appropriate usedShape for the new view type.
  1288. //------------------------------------------------------------------------------
  1289. SOM_Scope    ODShape*
  1290. SOMLINK        PictureViewer__CalculateUsedShape
  1291.             (
  1292.                 SampleCode_PictureViewer*    somSelf,
  1293.                 Environment*                ev,
  1294.                 ODFrame*                    frame
  1295.             )
  1296. {
  1297.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  1298.     SampleCode_PictureViewerMethodDebug("PictureViewer","CalculateUsedShape");
  1299.  
  1300.     Rect        bounds;
  1301.     RgnHandle    usedRgn     = kODNULL;
  1302.     ODShape*    usedShape    = kODNULL;
  1303.     ODTypeToken view        = frame->GetViewType(ev);
  1304.     
  1305.     ODVolatile(usedShape);
  1306.     ODVolatile(usedRgn);
  1307.  
  1308.     SOM_TRY
  1309.         // If the view is "frame", we intentionally return a nil shape;
  1310.         // doing so, will reset the used shape to equal the frame shape.
  1311.  
  1312.         if ( view == gGlobals->fLargeIconView ||
  1313.                 view == gGlobals->fSmallIconView ||
  1314.                 view == gGlobals->fThumbnailView )
  1315.         {
  1316.             usedRgn = ODNewRgn();
  1317.  
  1318.             if ( view == gGlobals->fLargeIconView || view == gGlobals->fSmallIconView )
  1319.             {
  1320.                 CUsingLibraryResources res;
  1321.  
  1322.                 // Set the bounds rect for the icon size.
  1323.                 SetRect(&bounds, 0, 0,
  1324.                             (view == gGlobals->fLargeIconView) ? kODLargeIconSize : kODSmallIconSize,
  1325.                             (view == gGlobals->fLargeIconView) ? kODLargeIconSize : kODSmallIconSize);
  1326.  
  1327.                 // Convert the icon mask into a Region.
  1328.                 THROW_IF_ERROR( IconIDToRgn(usedRgn, &bounds, atAbsoluteCenter, kBaseResourceID) );
  1329.             }
  1330.             else if ( view == gGlobals->fThumbnailView )
  1331.             {    
  1332.                 SetRect(&bounds, 0, 0, kODThumbnailSize, kODThumbnailSize);
  1333.                 RectRgn(usedRgn, &bounds);
  1334.             }
  1335.             
  1336.             usedShape = frame->CreateShape(ev);
  1337.             usedShape->SetQDRegion(ev, usedRgn);
  1338.     }
  1339.     SOM_CATCH_ALL
  1340.         ODDisposeHandle((ODHandle)usedRgn);
  1341.         ODSafeReleaseObject(usedShape);
  1342.         usedShape = kODNULL;
  1343.     SOM_ENDTRY
  1344.     
  1345.     return usedShape;
  1346. }
  1347.  
  1348. //------------------------------------------------------------------------------
  1349. // Method:        CleanupWindow
  1350. // Origin:        PictureViewer
  1351. //
  1352. // Description:    This method is called by the part when a window needs to be
  1353. //                cleaned up for a frame being closed/removed.
  1354. //
  1355. //                The part deallocates the window buffer allocated in the
  1356. //                CreateWindow() method.
  1357. //------------------------------------------------------------------------------
  1358. SOM_Scope    void
  1359. SOMLINK        PictureViewer__CleanupWindow
  1360.             (
  1361.                 SampleCode_PictureViewer*    somSelf,
  1362.                 Environment*                ev,
  1363.                 ODFrame*                    frame
  1364.             )
  1365. {
  1366.     SampleCode_PictureViewerMethodDebug("PictureViewer","CleanupWindow");
  1367.     
  1368.        TRY
  1369.         CFrameInfo*    frameInfo = (CFrameInfo*)frame->GetPartInfo(ev);
  1370.         if ( frameInfo->ShouldDisposeWindow() )
  1371.         {
  1372.             TempODWindow window = frame->AcquireWindow(ev);
  1373.             THROW_IF_NULL(window);
  1374.             
  1375.             ODPlatformWindow windowPtr = window->GetPlatformWindow(ev);
  1376.             CloseWindow(windowPtr);
  1377.             ODDisposePtr(windowPtr);
  1378.         }
  1379.     CATCH_ALL
  1380.         somSelf->HandleDialogBox(ev, frame, kErrorBoxID, kErrWindowGone);
  1381.         // consume excpetion because it's not fatal.
  1382.     ENDTRY
  1383. }
  1384.  
  1385. //------------------------------------------------------------------------------
  1386. // Method:        GetDefaultWindowProperties
  1387. // Origin:        PictureViewer
  1388. //
  1389. // Description:    This method sets up the default properties for the window to
  1390. //                be created (called from the Open method).
  1391. //------------------------------------------------------------------------------
  1392. SOM_Scope    WindowProperties*
  1393. SOMLINK        PictureViewer__GetDefaultWindowProperties
  1394.             (
  1395.                 SampleCode_PictureViewer*    somSelf,
  1396.                 Environment*                ev,
  1397.                 ODFrame*                    sourceFrame,
  1398.                 Rect*                        windowRect
  1399.             )
  1400. {
  1401.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  1402.     SampleCode_PictureViewerMethodDebug("PictureViewer","GetDefaultWindowProperties");
  1403.  
  1404.     WindowProperties*    windowProperties;
  1405.  
  1406.     ODVolatile(windowProperties);
  1407.     
  1408.     SOM_TRY
  1409.     
  1410.         windowProperties = new WindowProperties;
  1411.             
  1412.         // Calculate the offset for the window based on the sourceFrame.    
  1413.         if ( sourceFrame )
  1414.             somSelf->CalcPartWindowPosition(ev, sourceFrame, windowRect);
  1415.         else
  1416.             OffsetRect(windowRect, kALittleNudge,
  1417.                         GetMBarHeight() + kMacWindowTitleBarHeight);    
  1418.     
  1419.         // Set the window bounds based on the calculated rect.
  1420.         windowProperties->boundsRect = *windowRect;
  1421.     
  1422.         // Get the part's name to use for the new window.
  1423.         TempODIText windowName = GetPartName(ev, _fSelf, kODCategoryDrawing);
  1424.         // Convert the ODIText into a Pascal string.
  1425.         GetITextString(windowName, windowProperties->title);
  1426.         
  1427.         // Fill in the other fields of the Window Properties struct.
  1428.         windowProperties->procID = zoomDocProc;
  1429.         windowProperties->hasCloseBox = kODTrue;
  1430.         windowProperties->refCon = (long)kODNULL;
  1431.         windowProperties->wasVisible = kODFalse;
  1432.         windowProperties->isResizable = kODTrue;
  1433.         windowProperties->isFloating = kODFalse;
  1434.         windowProperties->isRootWindow = sourceFrame ? kODFalse : kODTrue;
  1435.         windowProperties->shouldShowLinks = kODFalse;
  1436.         windowProperties->sourceFrame = sourceFrame;
  1437.         
  1438.     SOM_CATCH_ALL
  1439.         ODDeleteObject(windowProperties);
  1440.     SOM_ENDTRY
  1441.     
  1442.     return windowProperties;
  1443. }
  1444.  
  1445. //------------------------------------------------------------------------------
  1446. // Method:        GetSavedWindowProperties
  1447. // Origin:        PictureViewer
  1448. //
  1449. // Description:    This method is called from the Open method when the frame
  1450. //                 is the root frame of an existing document.
  1451. //------------------------------------------------------------------------------
  1452. SOM_Scope    WindowProperties*
  1453. SOMLINK        PictureViewer__GetSavedWindowProperties
  1454.             (    
  1455.                 SampleCode_PictureViewer*        somSelf, 
  1456.                 Environment*                    ev,
  1457.                 ODFrame*                        frame
  1458.             )
  1459. {
  1460.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  1461.     SampleCode_PictureViewerMethodDebug("PictureViewer","GetSavedWindowProperties");
  1462.    
  1463.     RgnHandle             windowRgn = kODNULL;
  1464.     WindowProperties*     windowProperties;
  1465.  
  1466.     ODVolatile(windowRgn);
  1467.     ODVolatile(windowProperties);
  1468.     
  1469.    SOM_TRY
  1470.         windowProperties = new WindowProperties;
  1471.             
  1472.         // If we fail to load the window properties from storage, delete
  1473.         // the structure so the calling code will behave appropriately.    
  1474.         if ( BeginGetWindowProperties(ev, frame, windowProperties) )
  1475.         {    
  1476.             // Note: We don't call EndGetWindowProperties because it releases
  1477.             // the source frame, which we will need after this method returns.
  1478.             
  1479.             // Get the part's name to use for the new window.
  1480.             TempODIText windowName = GetPartName(ev, _fSelf, kODCategoryDrawing);
  1481.             // Convert the ODIText into a Pascal string.
  1482.             GetITextString(windowName, windowProperties->title);
  1483.         
  1484.             // Verify the window is still visible on a monitor.
  1485.             windowRgn = ODNewRgn();
  1486.             ODBoolean repositionWindow = kODFalse;
  1487.             
  1488.             // We are only concerned with the window's title bar being
  1489.             // visible, so calcuate the titlebar rect from the current
  1490.             // window bounds.
  1491.             Rect adjustedBounds = windowProperties->boundsRect;
  1492.             adjustedBounds.bottom = adjustedBounds.top;
  1493.             adjustedBounds.top -= kMacWindowTitleBarHeight;
  1494.             
  1495.             // Intersect the monitor's region
  1496.             RectRgn(windowRgn, &adjustedBounds);
  1497.             SectRgn(windowRgn, GetGrayRgn(), windowRgn);
  1498.             
  1499.             if ( !EmptyRgn(windowRgn) )
  1500.             {
  1501.                 // If the visible portion of the window is too small, we need
  1502.                 // to reposition it.
  1503.                 Rect intersectedBounds = (**windowRgn).rgnBBox;
  1504.                 if ( (intersectedBounds.right-intersectedBounds.left < kMinHorzVisPortion) ||
  1505.                         (intersectedBounds.bottom-intersectedBounds.top < kMinVertVisPortion) )
  1506.                     repositionWindow = kODTrue;
  1507.             }
  1508.             else
  1509.             {
  1510.                 // If the window is completely offscreen, we need to reposition it.
  1511.                 repositionWindow = kODTrue;
  1512.             }
  1513.     
  1514.             // Dispose of the allocated memory.
  1515.             ODDisposeHandle((ODHandle)windowRgn);
  1516.             windowRgn = kODNULL;
  1517.             
  1518.             // If not, we need to move it so the user can see it.
  1519.             if ( repositionWindow )
  1520.             {
  1521.                 Rect windowRect = windowProperties->boundsRect;
  1522.                 // Move the window to {0,0} coordinates.
  1523.                 OffsetRect(&windowRect, -windowRect.left, -windowRect.top);
  1524.                 // Now move the window to the default window position.
  1525.                 OffsetRect(&windowRect, kALittleNudge, GetMBarHeight() + kMacWindowTitleBarHeight);
  1526.                 // Save the new window position in our windowProperties.
  1527.                 windowProperties->boundsRect = windowRect;
  1528.             }
  1529.         }
  1530.         else
  1531.         {
  1532.             // If we were unable to re-load window properties,
  1533.             // dispose of the struct.
  1534.             ODDeleteObject(windowProperties);
  1535.         }
  1536.     
  1537.     SOM_CATCH_ALL
  1538.         if ( windowRgn != kODNULL )
  1539.             ODDisposeHandle((ODHandle)windowRgn);
  1540.         ODDeleteObject(windowProperties);
  1541.     SOM_ENDTRY
  1542.     
  1543.     return windowProperties;
  1544. }
  1545.  
  1546. //------------------------------------------------------------------------------
  1547. // Method:        CheckAndAddProperties
  1548. // Origin:        PictureViewer
  1549. //
  1550. // Description:    This method is called to prepare the storage unit 
  1551. //                during the creation of stationery, and to verify 
  1552. //                that all the properties we need are present during
  1553. //                externalization. .
  1554. //
  1555. //                The part adds the default content property, a preferred editor
  1556. //                property (to aid in part binding), a display frames
  1557. //                property, and a display setting property (cropped/scaled).
  1558. //
  1559. // Note:        The function StorageUnitSetValue is a macro which
  1560. //                simplifies the use of ODByteArrary, which is required
  1561. //                in the StorageUnit interface. Look in StorUtil.h/cpp for
  1562. //                an example of using the ODByteArray struct.
  1563. //------------------------------------------------------------------------------
  1564. SOM_Scope    void
  1565. SOMLINK        PictureViewer__CheckAndAddProperties
  1566.             (
  1567.                 SampleCode_PictureViewer*    somSelf,
  1568.                 Environment*                ev,
  1569.                 ODStorageUnit*                storageUnit
  1570.             )
  1571. {
  1572.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  1573.     SampleCode_PictureViewerMethodDebug("PictureViewer","CheckAndAddProperties");
  1574.  
  1575.     SOM_TRY
  1576.  
  1577.     // Create our content property.
  1578.     if ( !storageUnit->Exists(ev, kODPropContents, kODNULL, 0) )
  1579.         storageUnit->AddProperty(ev, kODPropContents);
  1580.     if ( !storageUnit->Exists(ev, kODPropContents, gGlobals->fPictScrapKind, 0) )
  1581.     {
  1582.         storageUnit->Focus(ev, kODPropContents, kODPosUndefined, kODNULL, 0, kODPosUndefined);
  1583.         storageUnit->AddValue(ev, gGlobals->fPictScrapKind);
  1584.     }
  1585.  
  1586.     // Since we are setting up the preferred kind property, we just write
  1587.     // out our default "kind" for the editor. We can write out the user
  1588.     // chosen kind in the ExternalizeStateInfo method.
  1589.  
  1590.     if ( !storageUnit->Exists(ev, kODPropPreferredKind, kODISOStr, 0) )
  1591.     {
  1592.         TRY
  1593.             ODSetISOStrProp(ev, storageUnit, kODPropPreferredKind, kODISOStr,
  1594.                                 gGlobals->fPictScrapKind);
  1595.         CATCH_ALL
  1596.             // Remove the property and value if something went wrong.
  1597.             // OpenDoc looks at this value, so if not valid, be sure
  1598.             // it doesn't exist.
  1599.             ODSURemoveProperty(ev, storageUnit, kODPropPreferredKind);
  1600.         ENDTRY
  1601.     }
  1602.  
  1603.     // Add our display frame list.
  1604.     if ( !storageUnit->Exists(ev, kODPropDisplayFrames, kODNULL, 0) )
  1605.         storageUnit->AddProperty(ev, kODPropDisplayFrames);
  1606.     if ( !storageUnit->Exists(ev, kODPropDisplayFrames, kODWeakStorageUnitRefs, 0) )
  1607.     {
  1608.         storageUnit->Focus(ev, kODPropDisplayFrames, kODPosUndefined, kODNULL, 0, kODPosUndefined);
  1609.         storageUnit->AddValue(ev, kODWeakStorageUnitRefs);
  1610.     }
  1611.     
  1612.     // Add the display mode value (crop/scale).
  1613.  
  1614.     if ( !storageUnit->Exists(ev, kPropDisplayMode, kODNULL, 0) )
  1615.         storageUnit->AddProperty(ev, kPropDisplayMode);
  1616.         
  1617.     if ( !storageUnit->Exists(ev, kPropDisplayMode, kODSLong, 0) )
  1618.     {
  1619.         storageUnit->Focus(ev, kPropDisplayMode, kODPosUndefined, kODNULL, 0, kODPosUndefined);
  1620.         storageUnit->AddValue(ev, kODSLong);
  1621.     }
  1622.  
  1623.     SOM_CATCH_ALL
  1624.     SOM_ENDTRY
  1625. }
  1626.  
  1627. //------------------------------------------------------------------------------
  1628. // Method:        ReadPartInfo
  1629. // Origin:        ODPart
  1630. //
  1631. // Description:    When a frame is being internalized by the Draft, it will ask
  1632. //                the owner (part) to read in its info annotation on the frame.
  1633. //
  1634. //                The part info class knows how to internalize itself from a
  1635. //                storage unit view, so we just call InitFromStorage.
  1636. //------------------------------------------------------------------------------
  1637. SOM_Scope    ODInfoType
  1638. SOMLINK        PictureViewer__ReadPartInfo
  1639.             (
  1640.                 SampleCode_PictureViewer*    somSelf,
  1641.                 Environment*                ev,
  1642.                 ODFrame*                    frame,
  1643.                 ODStorageUnitView*             storageUnitView
  1644.             )
  1645. {
  1646.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  1647.     SampleCode_PictureViewerMethodDebug("PictureViewer","ReadPartInfo");
  1648.  
  1649.     CFrameInfo* frameInfo = new CFrameInfo(_fSession);
  1650.     
  1651.     SOM_TRY        
  1652.         // Ask the info class to internalize itself.
  1653.         frameInfo->InitFromStorage(ev, storageUnitView);
  1654.         
  1655.         // We want to insure that frame negotiation only occurs once.
  1656.         // Thus, we set the flag to true since we are being internalized
  1657.         // from storage, meaning we've already performed frame negotiation
  1658.         // in the "FacetAdded" method.
  1659.         frameInfo->SetNegotiationFlag(kODTrue);
  1660.         
  1661.     SOM_CATCH_ALL
  1662.         // Clean up the allocated memory.
  1663.         ODDeleteObject(frameInfo);
  1664.     SOM_ENDTRY
  1665.     
  1666.     return (ODInfoType)frameInfo;
  1667. }
  1668.  
  1669. //------------------------------------------------------------------------------
  1670. // Method:        ClonePartInfo
  1671. // Origin:        ODPart
  1672. //
  1673. // Description:    When a frame is being cloned by the Draft, it will ask the owner
  1674. //                (part) to clone its info annotation on the frame.
  1675. //
  1676. //                The part uses a C++ helper class to encapsulate the information
  1677. //                we store with each frame, so we let it clone itself to the
  1678. //                storage unit view.
  1679. //------------------------------------------------------------------------------
  1680. SOM_Scope void
  1681. SOMLINK PictureViewer__ClonePartInfo
  1682.         (
  1683.             SampleCode_PictureViewer*    somSelf,
  1684.             Environment*                ev,
  1685.             ODDraftKey                     key,
  1686.             ODInfoType                     partInfo,
  1687.             ODStorageUnitView*             storageUnitView,
  1688.             ODFrame*                     scopeFrame
  1689.         )
  1690. {
  1691.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  1692.     SampleCode_PictureViewerMethodDebug("PictureViewer","ClonePartInfo");
  1693.  
  1694.     SOM_TRY
  1695.         // Tell our frame info class to write itself out into the pre-
  1696.         // focused storage unit.
  1697.         ((CFrameInfo*)partInfo)->CloneInto(ev, key, storageUnitView, scopeFrame);
  1698.     SOM_CATCH_ALL
  1699.     SOM_ENDTRY
  1700. }
  1701.  
  1702. //------------------------------------------------------------------------------
  1703. // Method:        WritePartInfo
  1704. // Origin:        ODPart
  1705. //
  1706. // Description:    When a frame is being externalized by the Draft, it
  1707. //                will ask the owner (part) to write out its info
  1708. //                annotation on the frame.
  1709. //
  1710. //                The part info class knows how to externalize itself
  1711. //                to a storage unit view, so we just call Externalize.
  1712. //------------------------------------------------------------------------------
  1713. SOM_Scope void
  1714. SOMLINK PictureViewer__WritePartInfo
  1715.         (
  1716.             SampleCode_PictureViewer*    somSelf,
  1717.             Environment*                ev,
  1718.             ODInfoType                    partInfo,
  1719.             ODStorageUnitView*            storageUnitView
  1720.         )
  1721. {
  1722.     SampleCode_PictureViewerMethodDebug("PictureViewer","WritePartInfo");
  1723.     
  1724.     SOM_TRY
  1725.         // Tell our frame info class to write itself out to
  1726.         // the pre-focused storage unit.
  1727.         ((CFrameInfo*)partInfo)->Externalize(ev, storageUnitView);
  1728.     SOM_CATCH_ALL
  1729.     SOM_ENDTRY
  1730. }
  1731.  
  1732. //------------------------------------------------------------------------------
  1733. // Method:        Open
  1734. // Origin:        ODPart
  1735. //
  1736. // Description:    This method is called when OpenDoc, a containing part, or
  1737. //                the active editor/viewer would like to open a frame into
  1738. //                a seperate window. If a source frame is passed into
  1739. //                this method, the editor/viewer is being asked to open a
  1740. //                part window.
  1741. //
  1742. //                The part first checks to see if the display frame has
  1743. //                been opened into a window before (this will be true
  1744. //                if a source frame is passed into the method and if
  1745. //                the source frame has a valid window ID). If there is
  1746. //                already a window displaying the frame, just bring that
  1747. //                window to the front. If not, we create a window from
  1748. //                scratch and display it.
  1749. //------------------------------------------------------------------------------
  1750. SOM_Scope    ODID
  1751. SOMLINK        PictureViewer__Open
  1752.             (
  1753.                 SampleCode_PictureViewer*    somSelf,
  1754.                 Environment*                ev,
  1755.                 ODFrame*                    frame
  1756.             )
  1757. {
  1758.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  1759.     SampleCode_PictureViewerMethodDebug("PictureViewer","Open");
  1760.  
  1761.     ODID                windowID = kODNULLID;
  1762.     TempODWindow        window(kODNULL);
  1763.     WindowProperties*    windowProperties = kODNULL;
  1764.     ODBoolean            adjustShape = kODFalse;
  1765.     
  1766.     ODVolatile(windowProperties);
  1767.  
  1768.     SOM_TRY
  1769.         // Because the frame parameter being passed to us can be one of
  1770.         // three things, we must determine what it is; either the root
  1771.         // frame of an existing document, the source frame for a part
  1772.         // window, or null if we are opening a new document.
  1773.     
  1774.         if ( frame == kODNULL )
  1775.         {
  1776.             // Calculate the bounding rectangle for a new window
  1777.             Rect windowRect = somSelf->CalcPartWindowSize(ev, kODNULL);
  1778.             // Get the default setting for a document window.
  1779.             windowProperties = somSelf->GetDefaultWindowProperties(ev, kODNULL, &windowRect);
  1780.             // Create a Mac Window and register it with OpenDoc.
  1781.             window = somSelf->CreateWindow(ev, kODNULL, kODFrameObject, windowProperties);
  1782.         }
  1783.         else if ( frame->IsRoot(ev) )
  1784.         {
  1785.             // Get the previously saved settings for the document window.
  1786.             windowProperties = somSelf->GetSavedWindowProperties(ev, frame);
  1787.             
  1788.             if ( windowProperties == kODNULL )
  1789.             {
  1790.                 // Calculate the bounding rectangle for a new window
  1791.                 Rect windowRect = somSelf->CalcPartWindowSize(ev, frame);
  1792.                 // Get the default setting for a document window.
  1793.                 windowProperties = somSelf->GetDefaultWindowProperties(ev, kODNULL, &windowRect);
  1794.             }
  1795.  
  1796.             // Set the adjustShape flag to true so the window will be adjusted later.
  1797.             adjustShape = kODTrue;
  1798.  
  1799.             // Create a Mac Window and register it with OpenDoc.
  1800.             window = somSelf->CreateWindow(ev, frame, kODFrameObject, windowProperties);
  1801.             
  1802.             // We release the source frame here because we didn't call
  1803.             // EndGetWindowProperties and becuase we are done with it.
  1804.             ODReleaseObject(ev, windowProperties->sourceFrame);
  1805.         }
  1806.         else // frame is a source frame
  1807.         {
  1808.             window = somSelf->AcquireFramesWindow(ev, frame);
  1809.     
  1810.             if ( window == kODNULL )
  1811.             {
  1812.  
  1813.                 // Calculate the bounding rectangle for a new window
  1814.                 Rect windowRect = somSelf->CalcPartWindowSize(ev, frame);
  1815.  
  1816.                 // Get the default setting for a document window.
  1817.                 windowProperties = somSelf->GetDefaultWindowProperties(ev, frame, &windowRect);
  1818.  
  1819.                 // Create a Mac Window and register it with OpenDoc.
  1820.                 window = somSelf->CreateWindow(ev, kODNULL, kODFrameObject, windowProperties);
  1821.  
  1822.                 // Tell the source frame that it is opened in a part window.
  1823.                 CFrameInfo* frameInfo = (CFrameInfo*)frame->GetPartInfo(ev);
  1824.                 frameInfo->SetPartWindow(ev, window);
  1825.             }
  1826.         }
  1827.     
  1828.         if ( window )
  1829.         {
  1830.             window->Open(ev);
  1831.             
  1832.             // The following is needed in cases such as drag and drop to the 
  1833.             // Finder. The window needs to adjust its shape and clip shape.
  1834.             if ( adjustShape )
  1835.                 window->AdjustWindowShape(ev);
  1836.     
  1837.             // Make the window visible.
  1838.             window->Show(ev);
  1839.             // Activate and select the window.
  1840.             window->Select(ev);
  1841.  
  1842.             // Get window id for return result.
  1843.             windowID = window->GetID(ev);
  1844.         }
  1845.     
  1846.         // Cleanup allocated memory.
  1847.         ODDeleteObject(windowProperties);
  1848.             
  1849.     SOM_CATCH_ALL
  1850.         // If we threw early, the source frame's refcount may be too high.
  1851.         if ( windowProperties )
  1852.             ODSafeReleaseObject(windowProperties->sourceFrame);
  1853.         // Cleanup the created items.
  1854.         ODDeleteObject(windowProperties);
  1855.         windowID = kODNULLID;
  1856.     SOM_ENDTRY
  1857.  
  1858.     return windowID;
  1859. }
  1860.  
  1861. //------------------------------------------------------------------------------
  1862. // Method:        DisplayFrameAdded
  1863. // Origin:        ODPart
  1864. //
  1865. // Description:    This method is called in response to a frame being
  1866. //                created for our part.
  1867. //
  1868. //                The part records the existence of a new display frame
  1869. //                in its internal display frame list, and verifies that
  1870. //                the frame is set up correctly (eg, valid viewType). 
  1871. //                The part also creates and stores its frame info class 
  1872. //                in the new frame. 
  1873. //------------------------------------------------------------------------------
  1874. SOM_Scope    void
  1875. SOMLINK        PictureViewer__DisplayFrameAdded
  1876.             (
  1877.                 SampleCode_PictureViewer*    somSelf,
  1878.                 Environment*                ev,
  1879.                 ODFrame*                    frame
  1880.             )
  1881. {
  1882.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  1883.     SampleCode_PictureViewerMethodDebug("PictureViewer","DisplayFrameAdded");
  1884.  
  1885.     SOM_TRY
  1886.         // If we are being embedded in another part, the presentation field
  1887.         // will (most likely) be unset; we need to set it to something meaningful.
  1888.         // The view field may also be unset; if so, we prefer to be displayed
  1889.         // in a frame view.
  1890.  
  1891.         if ( frame->GetPresentation(ev) != gGlobals->fMainPresentation )
  1892.             frame->SetPresentation(ev, gGlobals->fMainPresentation);
  1893.         
  1894.         if ( frame->GetViewType(ev) == kODNullTypeToken )
  1895.             frame->SetViewType(ev, gGlobals->fFrameView);
  1896.             
  1897.         // Hang our state info off of the new display frame. We use the
  1898.         // CFrameInfo object for activation, updating, and window maintenance.
  1899.         CFrameInfo* frameInfo = new CFrameInfo(_fSession);
  1900.         frame->SetPartInfo(ev, (ODInfoType)frameInfo);
  1901.             
  1902.         // If the frame being added is a root frame, we know that a window
  1903.         // is associated with this frame. Notify ourselves that we need to 
  1904.         // clean it up when the frame goes away.
  1905.         if ( frame->IsRoot(ev) )
  1906.             frameInfo->SetShouldDisposeWindow(kODTrue);
  1907.         
  1908.         // The proxy class will refcount the frame passed to it, so we
  1909.         // don't need to worry about refcounting the display frame.
  1910.         CFrameProxy* proxy = new CFrameProxy;
  1911.         proxy->InitFrameProxy(ev,frame);
  1912.     
  1913.         // Add the proxy to the display frame collection.
  1914.         _fDisplayFrames->Add(proxy);
  1915.     
  1916.         // Since we maintain a persistent list of weak references to our
  1917.         // display frames, having one added to the part dirties it.
  1918.         somSelf->SetDirty(ev);
  1919.     SOM_CATCH_ALL
  1920.     SOM_ENDTRY
  1921. }
  1922.  
  1923. //------------------------------------------------------------------------------
  1924. // Method:        DisplayFrameRemoved
  1925. // Origin:        ODPart
  1926. //
  1927. // Description:    This method is called in response to a frame being
  1928. //                removed from our part.
  1929. //
  1930. //                The part removes the frame from its internal display
  1931. //                frame list and relinquishes any foci that it still owns. Lastly,
  1932. //                if the frame has a source frame (it was the root frame of a
  1933. //                part window), we will record the part window bounds so that 
  1934. //                any subsequent part windows opened on the source frame will
  1935. //                appear in the same location.
  1936. //------------------------------------------------------------------------------
  1937. SOM_Scope    void
  1938. SOMLINK        PictureViewer__DisplayFrameRemoved
  1939.             (
  1940.                 SampleCode_PictureViewer*        somSelf,
  1941.                 Environment*                    ev,
  1942.                 ODFrame*                        frame
  1943.             )
  1944. {
  1945.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  1946.     SampleCode_PictureViewerMethodDebug("PictureViewer","DisplayFrameRemoved");
  1947.  
  1948.     SOM_TRY
  1949.         CFrameInfo* frameInfo = (CFrameInfo*)frame->GetPartInfo(ev);
  1950.     
  1951.         // Make sure the frame going away does not own any foci. Forgetting
  1952.         // to do this, will cause a refcounting error when the frame
  1953.         // is deleted by the draft.
  1954.         somSelf->RelinquishAllFoci(ev, frame);
  1955.  
  1956.         // Clean up the display frame.
  1957.         somSelf->CleanupDisplayFrame(ev, frame, kFrameRemoved);
  1958.         // Clean up any associated window.
  1959.         somSelf->CleanupWindow(ev, frame);
  1960.  
  1961.         // Dispose of the frame's runtime state info.
  1962.         frame->SetPartInfo(ev, (ODInfoType) kODNULL);
  1963.         ODDeleteObject(frameInfo);
  1964.         
  1965.         // Remove the display frame from our collection.
  1966.         CListIterator fiter(_fDisplayFrames);
  1967.         for ( CFrameProxy* proxy = (CFrameProxy*)fiter.First();
  1968.                 fiter.IsNotComplete(); proxy = (CFrameProxy*)fiter.Next() )
  1969.         {
  1970.             if ( ODObjectsAreEqual(ev, proxy->GetFrame(ev), frame) )
  1971.             {
  1972.                 // Delete the proxy object and its contents. The frame's
  1973.                 // refcount will be decremented in the proxy destructor.
  1974.                 fiter.RemoveCurrent();
  1975.                 delete proxy;
  1976.             }
  1977.         }
  1978.  
  1979.         // Since we maintain a persistent list of weak references to our
  1980.         // display frames, having one removed from the part dirties it.
  1981.         somSelf->SetDirty(ev);    
  1982.     SOM_CATCH_ALL
  1983.         // Alert the user of the problem.
  1984.         somSelf->HandleDialogBox(ev, frame, kErrorBoxID, kErrRemoveFrame);
  1985.         // Change the error code value so the DocShell doesn't
  1986.         // display an error dialog.
  1987.         SetErrorCode(kODErrAlreadyNotified);
  1988.     SOM_ENDTRY
  1989. }
  1990.  
  1991. //------------------------------------------------------------------------------
  1992. // Method:        DisplayFrameClosed
  1993. // Origin:        ODPart
  1994. //
  1995. // Description:    This method is called in response to a frame being
  1996. //                closed (not removed).
  1997. //------------------------------------------------------------------------------
  1998. SOM_Scope    void
  1999. SOMLINK        PictureViewer__DisplayFrameClosed
  2000.             (
  2001.                 SampleCode_PictureViewer*    somSelf,
  2002.                 Environment*                ev,
  2003.                 ODFrame*                    frame
  2004.             )
  2005. {
  2006.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  2007.     SampleCode_PictureViewerMethodDebug("PictureViewer","DisplayFrameClosed");
  2008.  
  2009.     SOM_TRY
  2010.         // Make sure the frame going away does not own any foci. Forgetting
  2011.         // to do this, will cause a refcounting error when the frame is
  2012.         // deleted by the draft.
  2013.         somSelf->RelinquishAllFoci(ev, frame);
  2014.  
  2015.         // Clean up the display frame.
  2016.         somSelf->CleanupDisplayFrame(ev, frame, kFrameClosed);
  2017.         // Clean up any associated window.
  2018.         somSelf->CleanupWindow(ev, frame);
  2019.         // Dispose of the frame's runtime state info.
  2020.         CFrameInfo* frameInfo = (CFrameInfo*)frame->GetPartInfo(ev);
  2021.         frame->SetPartInfo(ev, (ODInfoType)kODNULL);
  2022.         ODDeleteObject(frameInfo);
  2023.  
  2024.         // Remove the display frame from our collection.
  2025.         CListIterator fiter(_fDisplayFrames);
  2026.         for ( CFrameProxy* proxy = (CFrameProxy*)fiter.First();
  2027.                 fiter.IsNotComplete(); proxy = (CFrameProxy*)fiter.Next() )
  2028.         {
  2029.             if ( proxy->GetID() == frame->GetID(ev) )
  2030.             {
  2031.                 // Release the frame reference, but don't get rid of the
  2032.                 // proxy object because "closed" frames may be reconnected
  2033.                 // before the document is really closed.
  2034.                 proxy->Purge(ev);
  2035.             }
  2036.         }
  2037.         
  2038.     SOM_CATCH_ALL
  2039.         // Alert the user of the problem.
  2040.         somSelf->HandleDialogBox(ev, frame, kErrorBoxID, kErrRemoveFrame);
  2041.         // Change the error code value so the DocShell doesn't
  2042.         // display an error dialog.
  2043.         SetErrorCode(kODErrAlreadyNotified);
  2044.     SOM_ENDTRY
  2045. }
  2046.  
  2047. //------------------------------------------------------------------------------
  2048. // Method:        DisplayFrameConnected
  2049. // Origin:        ODPart
  2050. //
  2051. // Description:    This method is called when a display frame (ours or another
  2052. //                part's), was previously written out and is now being
  2053. //                internalized. It will be another part's data in instances
  2054. //                such as editor swapping. This methodis called instead of 
  2055. //                DisplayFrameAdded because a "new"frame is not being created; 
  2056. //                an existing one is being reconstituted.
  2057. //
  2058. //                The part first checks to see if it can match its frame to an
  2059. //                ID in the Display frame list; if so, it puts the frame into the
  2060. //                proxy. If not, we create a new proxy and then add the frame.
  2061. //
  2062. // Warning:        This method may be called during editor swapping, with a frame
  2063. //                not recognized by the part. This is okay. Just treat the case
  2064. //                as if a "new" frame were being added to the part.
  2065. //------------------------------------------------------------------------------
  2066. SOM_Scope    void
  2067. SOMLINK        PictureViewer__DisplayFrameConnected
  2068.             (
  2069.                 SampleCode_PictureViewer*    somSelf,
  2070.                 Environment*                ev,
  2071.                 ODFrame*                    frame
  2072.             )
  2073. {
  2074.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  2075.     SampleCode_PictureViewerMethodDebug("PictureViewer","DisplayFrameConnected");
  2076.  
  2077.     SOM_TRY
  2078.  
  2079.     // Iterate over our display collection to match the frame with
  2080.     // an existing proxy with the correct frame ID. If we find it,
  2081.     // replace the ID with the actual frame. If we don't find it,
  2082.     // treat it as a newly "added" frame.
  2083.     ODBoolean found = kODFalse;
  2084.     CListIterator fiter(_fDisplayFrames);
  2085.     for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
  2086.             fiter.IsNotComplete() && !found; 
  2087.             proxy = (CFrameProxy*) fiter.Next() )
  2088.     {
  2089.         if ( proxy->GetID() == frame->GetID(ev) )
  2090.         {
  2091.             // The proxy class will refcount the frame passed to it, so we
  2092.             // don't need to worry about refcounting the display frame.
  2093.             proxy->SetFrame(ev, frame);
  2094.             found = kODTrue;
  2095.         }
  2096.     }
  2097.  
  2098.     // Parts typically operate under the assumption that they have previous
  2099.     // knowledge of a frame before it is connected to them. This knowledge
  2100.     // should come from having read in the frame reference when the part
  2101.     // was internalized. If the frame is an "unknown", the part was probably
  2102.     // bound to another editor's storage unit because the editor is missing or
  2103.     // the user changed the editor in the Info dialog. 
  2104.     if ( found )
  2105.     {
  2106.         // If a display frame is connected to us with an unrecognizable
  2107.         // presentation, we need to set it to something meaningful.
  2108.     
  2109.         if ( frame->GetPresentation(ev) != gGlobals->fMainPresentation )
  2110.             frame->SetPresentation(ev, gGlobals->fMainPresentation);
  2111.         
  2112.         if ( frame->IsRoot(ev) )
  2113.         {
  2114.             // If the frame being added is a root frame, we know that a window
  2115.             // is associated with this frame. Notify ourselves that we need to 
  2116.             // clean it up when the frame goes away.
  2117.             CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
  2118.             frameInfo->SetShouldDisposeWindow(kODTrue);
  2119.             
  2120.             // In addition, we need to verify that the frame is in "frame" view.
  2121.             // If the user dragged an icon from a document to Finder and then
  2122.             // opens the resultant document, the view would be "icon". However,
  2123.             // displaying an icon is useless, so we need to change the view to
  2124.             // frame.
  2125.             
  2126.             // NOTE: we first check to see if the view type is set
  2127.             // to "frame" view. If not, we set it. We perform this check
  2128.             // rather than just setting it in all instances, because that
  2129.             // would be costly.
  2130.             if ( frame->GetViewType(ev) != gGlobals->fFrameView )
  2131.                 frame->SetViewType(ev, gGlobals->fFrameView);    
  2132.         }
  2133.     }
  2134.     else
  2135.     {
  2136.         // If an unrecognizable frame is connected to us, treat it like a "new"
  2137.         // frame and call our method to add it.
  2138.         somSelf->DisplayFrameAdded(ev, frame);
  2139.     }
  2140.     
  2141.     SOM_CATCH_ALL
  2142.     SOM_ENDTRY
  2143. }
  2144.  
  2145. //------------------------------------------------------------------------------
  2146. // Method:        CleanupDisplayFrame
  2147. // Origin:        PictureViewer
  2148. //
  2149. // Description:    This method is called when a frame has been closed or removed.
  2150. //                The method cleans up the references and state information stored
  2151. //                in the CFrameInfo class.
  2152. //------------------------------------------------------------------------------
  2153. SOM_Scope    void
  2154. SOMLINK        PictureViewer__CleanupDisplayFrame
  2155.             (
  2156.                 SampleCode_PictureViewer*        somSelf,
  2157.                 Environment*                    ev,
  2158.                 ODFrame*                        frame,
  2159.                 ODBoolean                        frameRemoved
  2160.             )
  2161. {
  2162.     SampleCode_PictureViewerMethodDebug("PictureViewer","CleanupDisplayFrame");
  2163.  
  2164.     ODError        error = noErr;
  2165.     CFrameInfo*    frameInfo = (CFrameInfo*)frame->GetPartInfo(ev);
  2166.     
  2167.     TRY
  2168.         // If we are the root of a child window, we need to notify
  2169.         // our source frame that we are going away.
  2170.         if ( frameInfo->HasSourceFrame() )
  2171.         {
  2172.             ODFrame* sourceFrame = frameInfo->GetSourceFrame(ev);
  2173.             CFrameInfo* sourceFrameInfo = (CFrameInfo*)sourceFrame->GetPartInfo(ev);
  2174.             
  2175.             if ( frameRemoved )
  2176.             {
  2177.                 // Invalidate the source frame. We do this because the
  2178.                 // source frame may have a unique display when it has
  2179.                 // been opened into a part window. This forces the
  2180.                 // frame to redraw "not opened".
  2181.                 sourceFrame->Invalidate(ev, kODNULL, kODNULL);
  2182.             }
  2183.             
  2184.             // Tell the source frame that its dependent is going away.
  2185.             sourceFrameInfo->ReleaseDependentFrame(ev);            
  2186.  
  2187.             // Release our reference to the source frame.
  2188.             frameInfo->ReleaseSourceFrame(ev);
  2189.                 
  2190.             // If the frame is the root, it is a part window going away
  2191.             // and we need to notify our source frame that it no longer
  2192.             // has a part window.
  2193.             if ( frame->IsRoot(ev) )
  2194.                 sourceFrameInfo->SetPartWindow(ev, kODNULL);
  2195.         }
  2196.     CATCH_ALL
  2197.         error = ErrorCode();
  2198.     ENDTRY
  2199.     
  2200.     TRY
  2201.         // If the frame was removed from the document, we need to remove
  2202.         // any child window displaying that frame.
  2203.         if ( frameRemoved )
  2204.         {
  2205.             // If we have a child window, we need to close it.
  2206.             ODWindow* window = frameInfo->AcquirePartWindow(ev);
  2207.  
  2208.             if ( window )
  2209.             {
  2210.                 frameInfo->SetPartWindow(ev, kODNULL);
  2211.                 window->CloseAndRemove(ev);
  2212.             }
  2213.         }
  2214.     CATCH_ALL
  2215.         error = ErrorCode();
  2216.     ENDTRY
  2217.  
  2218.     TRY
  2219.         if ( frameInfo->HasDependentFrame() )
  2220.         {
  2221.             // Get the frame that is dependent on this one. We can safely
  2222.             // do this because we only reference our own display frames.
  2223.             ODFrame* dependentFrame = frameInfo->GetDependentFrame(ev);
  2224.             CFrameInfo* dependentFrameInfo = (CFrameInfo*)dependentFrame->GetPartInfo(ev);
  2225.  
  2226.             // Tell the dependent frame that its source is going away.
  2227.             dependentFrameInfo->ReleaseSourceFrame(ev);
  2228.             
  2229.             // Release our reference to the dependent frame.
  2230.             frameInfo->ReleaseDependentFrame(ev);
  2231.         }
  2232.     CATCH_ALL
  2233.         error = ErrorCode();
  2234.     ENDTRY
  2235.     
  2236.     // If anything went wrong, signal an error.
  2237.     THROW_IF_ERROR(error);
  2238. }
  2239.  
  2240. //------------------------------------------------------------------------------
  2241. // Method:        FrameShapeChanged
  2242. // Origin:        ODPart
  2243. //
  2244. // Description:    This method is called in response to a frame's shape being
  2245. //                altered, either by the user or the part we are embedded in.
  2246. //
  2247. //                To keep all dependent frames in sync, we need to propogate the
  2248. //                new frame shape to the frames dependent on the changed frame.
  2249. //                This is done by observing the display frames stored in the
  2250. //                frame info and calling RequestFrameShape for each.
  2251. //------------------------------------------------------------------------------
  2252. SOM_Scope    void
  2253. SOMLINK        PictureViewer__FrameShapeChanged
  2254.             (
  2255.                 SampleCode_PictureViewer*        somSelf,
  2256.                 Environment*                    ev,
  2257.                 ODFrame*                        frame
  2258.             )
  2259. {
  2260.     SampleCode_PictureViewerMethodDebug("PictureViewer","FrameShapeChanged");
  2261.  
  2262.     SOM_TRY
  2263.         // Adjust the "used" shape for the new frame shape.
  2264.         TempODShape usedShape = somSelf->CalculateUsedShape(ev, frame);
  2265.         frame->ChangeUsedShape(ev, usedShape, kODNULL);
  2266.     SOM_CATCH_ALL
  2267.     SOM_ENDTRY
  2268. }
  2269.  
  2270. //------------------------------------------------------------------------------
  2271. // Method:        FacetAdded
  2272. // Origin:        ODPart
  2273. //
  2274. // Description:    This method is called when any part adds a facet to
  2275. //                one of our display frames.
  2276. //------------------------------------------------------------------------------
  2277. SOM_Scope    void
  2278. SOMLINK        PictureViewer__FacetAdded
  2279.             (
  2280.                 SampleCode_PictureViewer*    somSelf,
  2281.                 Environment*                ev,
  2282.                 ODFacet*                    facet
  2283.             )
  2284. {
  2285.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  2286.     SampleCode_PictureViewerMethodDebug("PictureViewer","FacetAdded");
  2287.     
  2288.     SOM_TRY
  2289.         ODTypeToken    viewType;
  2290.         ODBoolean    isNegotiated;        // true if frame already negotiated
  2291.         ODFrame*    frame = facet->GetFrame(ev);
  2292.         CFrameInfo* frameInfo = (CFrameInfo*)frame->GetPartInfo(ev);
  2293.  
  2294.         viewType = frame->GetViewType(ev);
  2295.         isNegotiated = frameInfo->GetNegotiationFlag();
  2296.         
  2297.         if ( viewType == gGlobals->fFrameView && _fPicture && !isNegotiated )
  2298.         {
  2299.             // Perform frame negotiation to receive a frame shape
  2300.             // that will contain the picture.
  2301.     
  2302.             Rect        bounds;
  2303.             ODRect        pictRect;
  2304.             
  2305.             bounds = (**((PicHandle)_fPicture)).picFrame;
  2306.             OffsetRect(&bounds, -bounds.left, -bounds.top);
  2307.     
  2308.             IntToFixedRect(bounds, pictRect);    
  2309.     
  2310.             TempODShape    wantShape = frame->CreateShape(ev);
  2311.             wantShape->SetRectangle(ev, &pictRect);
  2312.     
  2313.             TempODShape result = frame->RequestFrameShape(ev, wantShape, kODNULL);
  2314.  
  2315.             // Notify the frame of the new shape
  2316.             frame->Invalidate(ev, kODNULL, kODNULL);
  2317.             
  2318.             frameInfo->SetNegotiationFlag(kODTrue);
  2319.         }
  2320.         
  2321.         // If a root facet is being added, the frame should be activated when the
  2322.         // window is "selected". This prevents OpenDoc from getting into an
  2323.         // ambiguous state of no part having the selection focus.
  2324.     
  2325.         if ( frame->IsRoot(ev) )
  2326.         {
  2327.             frameInfo->SetActiveFacet(facet);
  2328.             frameInfo->SetFrameReactivate(kODTrue);
  2329.         }
  2330.     
  2331.         // If a frame had all of its facets removed, the frame would have
  2332.         // hidden any of its part windows. If the frame becomes visible again,
  2333.         // by having a facet added to it, we will "show" the part window for
  2334.         // the frame.
  2335.         
  2336.         if ( (CountFacets(ev, frame) == 1) )
  2337.         {
  2338.             TempODWindow window = frameInfo->AcquirePartWindow(ev);
  2339.             if ( window ) 
  2340.                 window->Show(ev);
  2341.         }
  2342.     SOM_CATCH_ALL
  2343.     SOM_ENDTRY
  2344. }
  2345.  
  2346. //------------------------------------------------------------------------------
  2347. // Method:        FacetRemoved
  2348. // Origin:        ODPart
  2349. //
  2350. // Description:    This method is called when any part removes a facet from
  2351. //                one of our display frames.
  2352. //
  2353. //                The part just removes the "active" flag from the appropriate
  2354. //                display frame if necessary since this facet will not be
  2355. //                available, or active, again.
  2356. //------------------------------------------------------------------------------
  2357. SOM_Scope    void
  2358. SOMLINK        PictureViewer__FacetRemoved
  2359.             (
  2360.                 SampleCode_PictureViewer*        somSelf,
  2361.                 Environment*                    ev,
  2362.                 ODFacet*                        facet
  2363.             )
  2364. {
  2365.     SampleCode_PictureViewerMethodDebug("PictureViewer","FacetRemoved");
  2366.  
  2367.     ODFrame*    frame = facet->GetFrame(ev);
  2368.     CFrameInfo* frameInfo = (CFrameInfo*)facet->GetFrame(ev)->GetPartInfo(ev);
  2369.     TempODFrame    containingFrame = frame->AcquireContainingFrame(ev);
  2370.  
  2371.     SOM_TRY
  2372.         // If the facet was the active facet, it can no longer be.
  2373.         if ( ODObjectsAreEqual(ev, frameInfo->GetActiveFacet(), facet) )
  2374.             frameInfo->SetActiveFacet(kODNULL);
  2375.     
  2376.         // If a frame has all of its facets removed and its containing frame set
  2377.         // to NULL, the frame becomes "hidden". If the frame owns a part window,
  2378.         // the part window should also be hidden.
  2379.  
  2380.         if ( (CountFacets(ev, frame) == 0) && containingFrame == kODNULL )
  2381.         {
  2382.             TempODWindow window = frameInfo->AcquirePartWindow(ev);
  2383.             if ( window ) 
  2384.                 window->Hide(ev);
  2385.         }
  2386.     SOM_CATCH_ALL
  2387.     SOM_ENDTRY
  2388. }
  2389.  
  2390. //------------------------------------------------------------------------------
  2391. // Method:        AttachSourceFrame
  2392. // Origin:        ODPart
  2393. //
  2394. // Description:    If a part which we are contained in is opened into a part
  2395. //                window, it is required to iterate over its embedded frames and
  2396. //                add new display frames in the part window. After each new
  2397. //                embedded frame is created, this method will be called.
  2398. //
  2399. //                We just validate the frame in this part.
  2400. //------------------------------------------------------------------------------
  2401. SOM_Scope    void
  2402. SOMLINK        PictureViewer__AttachSourceFrame
  2403.             (
  2404.                 SampleCode_PictureViewer*    somSelf,
  2405.                 Environment*                ev,
  2406.                 ODFrame*                    frame,
  2407.                 ODFrame*                    sourceFrame
  2408.             )
  2409. {
  2410.     SampleCode_PictureViewerMethodDebug("PictureViewer","AttachSourceFrame");
  2411.  
  2412.     SOM_TRY
  2413.         // Tell the new frame about its source.
  2414.         CFrameInfo* frameInfo = (CFrameInfo*)frame->GetPartInfo(ev);
  2415.         frameInfo->SetSourceFrame(ev, sourceFrame);
  2416.         
  2417.         // And tell the source about its new dependent.
  2418.         frameInfo = (CFrameInfo*)sourceFrame->GetPartInfo(ev);
  2419.         frameInfo->SetDependentFrame(ev, frame);
  2420.         
  2421.         // In both cases, refcounting of the frame and sourceFrame is
  2422.         // handled by the CFrameInfo class.
  2423.     SOM_CATCH_ALL
  2424.     SOM_ENDTRY
  2425. }
  2426.  
  2427. //------------------------------------------------------------------------------
  2428. // Method:        ViewTypeChanged
  2429. // Origin:        ODPart
  2430. //
  2431. // Description:    This method is called when one of our display frame's viewType
  2432. //                field has been modified. We call this method on ourselves when
  2433. //                new display frames are added, but it can also be called when
  2434. //                the user changes the view in the "part info" dialog.
  2435. //------------------------------------------------------------------------------
  2436. SOM_Scope    void
  2437. SOMLINK        PictureViewer__ViewTypeChanged
  2438.             (
  2439.                 SampleCode_PictureViewer*        somSelf,
  2440.                 Environment*                    ev,
  2441.                 ODFrame*                        frame
  2442.             )
  2443. {
  2444.     SampleCode_PictureViewerMethodDebug("PictureViewer","ViewTypeChanged");
  2445.  
  2446.     SOM_TRY    
  2447.         // Change this frame's used shape to match the new view setting.
  2448.         TempODShape newUsedShape = somSelf->CalculateUsedShape(ev, frame);    
  2449.     
  2450.         frame->Invalidate(ev, kODNULL, kODNULL);
  2451.         frame->ChangeUsedShape(ev, newUsedShape, kODNULL);
  2452.         frame->Invalidate(ev, kODNULL, kODNULL);
  2453.     SOM_CATCH_ALL
  2454.             frame->SetViewType(ev, gGlobals->fFrameView);    
  2455.     SOM_ENDTRY
  2456. }
  2457.  
  2458. //------------------------------------------------------------------------------
  2459. // Method:        Draw
  2460. // Origin:        ODPart
  2461. //
  2462. // Description:    This method is called when a facet of a part's display
  2463. //                frame intersects the invalidated portion of an OpenDoc
  2464. //                window. The invalidShape parameter passed in is the
  2465. //                portion of the facet which has been invalidated.
  2466. //
  2467. //                The part sets up the drawing environment and then calls the
  2468. //                appropriate drawing method based on the frame's viewType.
  2469. //------------------------------------------------------------------------------
  2470. SOM_Scope    void
  2471. SOMLINK        PictureViewer__Draw
  2472.             (
  2473.                 SampleCode_PictureViewer*    somSelf,
  2474.                 Environment*                ev,
  2475.                 ODFacet*                    facet,
  2476.                 ODShape*                    invalidShape
  2477.             )
  2478. {
  2479.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  2480.     SampleCode_PictureViewerMethodDebug("PictureViewer","Draw");
  2481.  
  2482.     SOM_TRY
  2483.         // Focus the port and origin for drawing in our facet.
  2484.         // Note that this instance of the CFocus class is being
  2485.         // allocated on the stack. When the execution leaves the
  2486.         // scope of this method, the destructor (which cleans up
  2487.         // the drawing environment) is automatically called.
  2488.  
  2489.         CFocus initiateDrawing(ev, facet, invalidShape);
  2490.         
  2491.         ODTypeToken view = facet->GetFrame(ev)->GetViewType(ev);
  2492.         
  2493.         if ( view == gGlobals->fLargeIconView || view == gGlobals->fSmallIconView )
  2494.             somSelf->DrawIconView(ev, facet);
  2495.         else if ( view == gGlobals->fThumbnailView )
  2496.             somSelf->DrawThumbnailView(ev, facet);
  2497.         else
  2498.             somSelf->DrawFrameView(ev, facet);
  2499.     SOM_CATCH_ALL
  2500.     SOM_ENDTRY
  2501. }
  2502.  
  2503. //------------------------------------------------------------------------------
  2504. // Method:        DrawFrameView
  2505. // Origin:        PictureViewer
  2506. //
  2507. // Description:    This method is called by the part when the frame being
  2508. //                drawn is in "frame" view.
  2509. //------------------------------------------------------------------------------
  2510. SOM_Scope    void
  2511. SOMLINK        PictureViewer__DrawFrameView
  2512.              (
  2513.                 SampleCode_PictureViewer*        somSelf,
  2514.                 Environment*                    ev,
  2515.                 ODFacet*                        facet
  2516.             )
  2517. {
  2518.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  2519.     SampleCode_PictureViewerMethodDebug("PictureViewer","DrawFrameView");
  2520.  
  2521.     SOM_TRY
  2522.         if ( _fPicture )
  2523.         {
  2524.             GrafPtr        port;
  2525.             Rect         bounds;
  2526.             
  2527.             GetPort(&port);
  2528.             //• An optimization here would be to erase the 
  2529.             //  difference between the picture and clip shape.
  2530.             EraseRect(&port->portRect);
  2531.     
  2532.             if ( _fDisplayMode == kCommandScale )
  2533.             {
  2534.                 TempODShape frameShape = facet->GetFrame(ev)
  2535.                                         ->AcquireFrameShape(ev, kODNULL);
  2536.  
  2537.                 RgnHandle rgn = frameShape->GetQDRegion(ev);
  2538.                 bounds = (**rgn).rgnBBox;
  2539.                 OffsetRect(&bounds, -bounds.left, -bounds.top);
  2540.                 DrawPicture((PicHandle)_fPicture, &bounds);
  2541.             }
  2542.             else
  2543.             {
  2544.                 bounds = (**((PicHandle)_fPicture)).picFrame;
  2545.                 OffsetRect(&bounds, -bounds.left, -bounds.top);
  2546.                 DrawPicture((PicHandle)_fPicture, &bounds);
  2547.             }
  2548.         }
  2549.     SOM_CATCH_ALL
  2550.     SOM_ENDTRY
  2551. }
  2552.  
  2553. //------------------------------------------------------------------------------
  2554. // Method:        DrawIconView
  2555. // Origin:        PictureViewer
  2556. //
  2557. // Description:    This method is called by the part when the frame being
  2558. //                drawn is in "standard icon" view.
  2559. //
  2560. //                The part uses the Icon Utilities toolbox manager to
  2561. //                aid in drawing icons in active windows. The Guidelines
  2562. //                require a different appearance for selected icons in
  2563. //                inactive windows, which we do manually.
  2564. //------------------------------------------------------------------------------
  2565. SOM_Scope    void
  2566. SOMLINK        PictureViewer__DrawIconView
  2567.             (
  2568.                 SampleCode_PictureViewer*        somSelf,
  2569.                 Environment*                    ev,
  2570.                 ODFacet*                        facet
  2571.             )
  2572. {
  2573.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  2574.     SampleCode_PictureViewerMethodDebug("PictureViewer","DrawIconView");
  2575.  
  2576.     Rect                iconRect;
  2577.     IconTransformType     transformType = ttNone;
  2578.     CFrameInfo*            frameInfo;
  2579.     ODFrame*            frame; 
  2580.     ODTypeToken            viewType;
  2581.     
  2582.     SOM_TRY
  2583.         frame        = facet->GetFrame(ev);
  2584.         viewType    = frame->GetViewType(ev);
  2585.         frameInfo     = (CFrameInfo*)frame->GetPartInfo(ev);
  2586.         
  2587.         // Check to see if the facet is selected
  2588.         if ( facet->GetHighlight(ev) == kODFullHighlight )
  2589.             transformType = ttSelected;
  2590.         
  2591.         // Check to see if the frame has been opened into a part window.
  2592.         TempODWindow window = frameInfo->AcquirePartWindow(ev);
  2593.         if ( window && window->IsShown(ev) )
  2594.             transformType |= ttOpen;
  2595.         
  2596.         // Draw the icon.
  2597.         if ( viewType == gGlobals->fLargeIconView )
  2598.             SetRect(&iconRect, 0, 0, kODLargeIconSize, kODLargeIconSize);
  2599.         else // ( viewType == gGlobals->fSmallIconView )
  2600.             SetRect(&iconRect, 0, 0, kODSmallIconSize, kODSmallIconSize);
  2601.     
  2602.         CUsingLibraryResources res;
  2603.         PlotIconID(&iconRect, atAbsoluteCenter, transformType, kBaseResourceID);
  2604.     SOM_CATCH_ALL
  2605.     SOM_ENDTRY
  2606. }
  2607.  
  2608. //------------------------------------------------------------------------------
  2609. // Method:        DrawThumbnailView
  2610. // Origin:        PictureViewer
  2611. //
  2612. // Description:    This method is called by the part when the frame being
  2613. //                drawn in is in "thumbnail" view.
  2614. //------------------------------------------------------------------------------
  2615. SOM_Scope    void
  2616. SOMLINK        PictureViewer__DrawThumbnailView
  2617.              (
  2618.                 SampleCode_PictureViewer*    somSelf,
  2619.                 Environment*                ev,
  2620.                 ODFacet*                    facet
  2621.             )
  2622. {
  2623.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  2624.     SampleCode_PictureViewerMethodDebug("PictureViewer","DrawThumbnailView");
  2625.  
  2626.     SOM_TRY
  2627.         // If our thumbnail representation doesn't exist, try
  2628.         // recreating it.
  2629.         if ( !_fGWorld )
  2630.             somSelf->GenerateThumbnail(ev, facet->GetFrame(ev));
  2631.         
  2632.         if ( _fGWorld )
  2633.             DrawGWorldThumbnail(ev, (GWorldPtr)_fGWorld, facet);
  2634.         else
  2635.         {    // Offscreen gWorld not available. Just draw it.
  2636.             Rect    bounds;
  2637.             
  2638.             SetRect(&bounds, 0, 0, kODThumbnailSize, kODThumbnailSize);
  2639.             DrawPicture((PicHandle)_fPicture, &bounds);
  2640.         }
  2641.     SOM_CATCH_ALL
  2642.     SOM_ENDTRY
  2643. }
  2644.  
  2645. //------------------------------------------------------------------------------
  2646. // Method:        BeginRelinquishFocus
  2647. // Origin:        ODPart
  2648. //
  2649. // Description:    This method is called when another part (or possibly
  2650. //                ourself) is requesting a focus for one of its display
  2651. //                frames. Returning true means we are willing to give
  2652. //                up the requested focus.
  2653. //
  2654. //                The part will give up any focus except for the
  2655. //                modal focus. We don't want to give this up until we
  2656. //                are completely done displaying a modal dialog.
  2657. //------------------------------------------------------------------------------
  2658. SOM_Scope    ODBoolean
  2659. SOMLINK        PictureViewer__BeginRelinquishFocus
  2660.             (
  2661.                 SampleCode_PictureViewer*        somSelf,
  2662.                 Environment*                    ev,
  2663.                 ODTypeToken                        focus,
  2664.                 ODFrame*                        /*ownerFrame*/,
  2665.                 ODFrame*                        proposedFrame
  2666.             )
  2667. {
  2668.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  2669.     SampleCode_PictureViewerMethodDebug("PictureViewer","BeginRelinquishFocus");
  2670.  
  2671.     ODBoolean willRelinquish = kODTrue;
  2672.  
  2673.     SOM_TRY
  2674.         // Another part is trying to put up a Modal dialog while we
  2675.         // are currently displaying ours. Deny the request.
  2676.         if ( focus == gGlobals->fModalFocus )
  2677.         {
  2678.             TempODPart proposedPart = ODAcquirePart(ev,proposedFrame);
  2679.             if ( ODObjectsAreEqual(ev, proposedPart, _fSelf) == kODFalse )
  2680.                 willRelinquish = kODFalse;
  2681.         }    
  2682.     SOM_CATCH_ALL
  2683.         willRelinquish = kODFalse;
  2684.     SOM_ENDTRY
  2685.  
  2686.     return willRelinquish;
  2687. }
  2688.  
  2689. //------------------------------------------------------------------------------
  2690. // Method:        CommitRelinquishFocus
  2691. // Origin:        ODPart
  2692. //
  2693. // Description:    This method is called when it is actually time to give
  2694. //                up the requested focus.
  2695. //
  2696. //                The part calls its FocusLost method to handle the 
  2697. //                reliquishing of the particular focus.
  2698. //------------------------------------------------------------------------------
  2699. SOM_Scope    void
  2700. SOMLINK        PictureViewer__CommitRelinquishFocus
  2701.             (
  2702.                 SampleCode_PictureViewer*        somSelf,
  2703.                 Environment*                    ev,
  2704.                 ODTypeToken                        focus,
  2705.                 ODFrame*                        ownerFrame,
  2706.                 ODFrame*                        proposedFrame
  2707.             )
  2708. {
  2709.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  2710.     SampleCode_PictureViewerMethodDebug("PictureViewer","CommitRelinquishFocus");
  2711.  
  2712.     SOM_TRY
  2713.         // We agreed to give up the requested focus, so now we must do so.
  2714.         somSelf->FocusLost(ev, focus, ownerFrame);
  2715.     SOM_CATCH_ALL
  2716.     SOM_ENDTRY
  2717. }
  2718.  
  2719. //------------------------------------------------------------------------------
  2720. // Method:        AbortRelinquishFocus
  2721. // Origin:        ODPart
  2722. //
  2723. // Description:    This method is called when another part (or ourself) requested
  2724. //                a focus for one of its display frames, bet we returned kODFalse
  2725. //                from BeginRelinqishFocus() for one, or all, of the requested
  2726. //                foci. At this point, we are being told to resume ownership of 
  2727. //                the focus.
  2728. //------------------------------------------------------------------------------
  2729. SOM_Scope    void
  2730. SOMLINK        PictureViewer__AbortRelinquishFocus
  2731.             (
  2732.                 SampleCode_PictureViewer*        somSelf,
  2733.                 Environment*                    ev,
  2734.                 ODTypeToken                        focus,
  2735.                 ODFrame*                        ownerFrame,
  2736.                 ODFrame*                        /*proposedFrame*/
  2737.             )
  2738. {
  2739.     SampleCode_PictureViewerMethodDebug("PictureViewer","AbortRelinquishFocus");
  2740.     
  2741.     // Some parts may have suspended some events in the BeginRelinquishFocus
  2742.     // method. If so, they would resume those events here.
  2743. }
  2744.  
  2745. //------------------------------------------------------------------------------
  2746. // Method:        FocusAcquired
  2747. // Origin:        ODPart
  2748. //
  2749. // Description:    This method is called when the Arbitrator has
  2750. //                registered us as the "owner" of the particular focus.
  2751. //                This can occur if a focus is requested, or if a focus
  2752. //                is tranferred to one of the part's display frames.
  2753. //
  2754. //                The part will request its complete focus set to become active.
  2755. //                If the part is successful, we notify ourself to become active.
  2756. //------------------------------------------------------------------------------
  2757. SOM_Scope    void
  2758. SOMLINK        PictureViewer__FocusAcquired
  2759.             (
  2760.                 SampleCode_PictureViewer*        somSelf,
  2761.                 Environment*                    ev,
  2762.                 ODTypeToken                        focus,
  2763.                 ODFrame*                        ownerFrame
  2764.             )
  2765. {
  2766.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  2767.     SampleCode_PictureViewerMethodDebug("PictureViewer","FocusAcquired");
  2768.  
  2769.     ODArbitrator* arbitrator =  _fSession->GetArbitrator(ev);
  2770.  
  2771.     SOM_TRY
  2772.         if ( arbitrator->RequestFocusSet(ev, gGlobals->fUIFocusSet, ownerFrame) )
  2773.         {
  2774.             somSelf->PartActivated(ev, ownerFrame);
  2775.         }
  2776.     SOM_CATCH_ALL
  2777.     SOM_ENDTRY
  2778. }
  2779.  
  2780. //------------------------------------------------------------------------------
  2781. // Method:        FocusLost
  2782. // Origin:        ODPart
  2783. //
  2784. // Description:    This method is called when the Arbitrator has
  2785. //                unregistered us as the owner of a particular focus.
  2786. //------------------------------------------------------------------------------
  2787. SOM_Scope    void
  2788. SOMLINK        PictureViewer__FocusLost
  2789.             (
  2790.                 SampleCode_PictureViewer*    somSelf,
  2791.                 Environment*                ev,
  2792.                 ODTypeToken                    focus,
  2793.                 ODFrame*                    ownerFrame
  2794.             )
  2795. {
  2796.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  2797.     SampleCode_PictureViewerMethodDebug("PictureViewer","FocusLost");
  2798.  
  2799.     SOM_TRY
  2800.         if ( focus == gGlobals->fSelectionFocus )
  2801.         {
  2802.             CFrameInfo* frameInfo = (CFrameInfo*)ownerFrame->GetPartInfo(ev);
  2803.             frameInfo->SetFrameActive(kODFalse);
  2804.         }
  2805.     SOM_CATCH_ALL
  2806.     SOM_ENDTRY
  2807. }
  2808.  
  2809. //------------------------------------------------------------------------------
  2810. // Method:        RelinquishAllFoci
  2811. // Origin:        PictureViewer
  2812. //
  2813. // Description:    This method is called when a frame is going away. The method
  2814. //                relinquishes all foci the frame owns.
  2815. //------------------------------------------------------------------------------
  2816. SOM_Scope    void
  2817. SOMLINK        PictureViewer__RelinquishAllFoci
  2818.             (
  2819.                 SampleCode_PictureViewer*        somSelf,
  2820.                 Environment*                    ev,
  2821.                 ODFrame*                        frame
  2822.             )
  2823. {
  2824.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  2825.     SampleCode_PictureViewerMethodDebug("PictureViewer","RelinquishAllFoci");
  2826.  
  2827.     ODArbitrator* arbitrator = _fSession->GetArbitrator(ev);
  2828.         
  2829.     TRY
  2830.         TempODFrame focusFrame = arbitrator->AcquireFocusOwner(ev, gGlobals->fSelectionFocus);
  2831.         if ( ODObjectsAreEqual(ev, focusFrame, frame) )
  2832.         {
  2833.             arbitrator->RelinquishFocus(ev, gGlobals->fSelectionFocus, frame);
  2834.             somSelf->FocusLost(ev, gGlobals->fSelectionFocus, frame);
  2835.         }
  2836.     CATCH_ALL
  2837.     ENDTRY
  2838.  
  2839.     TRY
  2840.         TempODFrame focusFrame = arbitrator->AcquireFocusOwner(ev, gGlobals->fMenuFocus);
  2841.         if ( ODObjectsAreEqual(ev, focusFrame, frame) )
  2842.         {
  2843.             arbitrator->RelinquishFocus(ev, gGlobals->fMenuFocus, frame);
  2844.             somSelf->FocusLost(ev, gGlobals->fMenuFocus, frame);
  2845.         }
  2846.     CATCH_ALL
  2847.     ENDTRY
  2848.  
  2849.     TRY
  2850.         TempODFrame focusFrame = arbitrator->AcquireFocusOwner(ev, gGlobals->fClipboardFocus);
  2851.         if ( ODObjectsAreEqual(ev, focusFrame, frame) )
  2852.         {
  2853.             arbitrator->RelinquishFocus(ev, gGlobals->fClipboardFocus, frame);
  2854.             somSelf->FocusLost(ev, gGlobals->fClipboardFocus, frame);
  2855.         }
  2856.     CATCH_ALL
  2857.     ENDTRY
  2858. }
  2859.  
  2860. //------------------------------------------------------------------------------
  2861. // Method:        CloneInto
  2862. // Origin:        ODPersistentObject
  2863. //
  2864. // Description:    This method is called during cloning, typically during data
  2865. //                Interchange operations. The part should write out its current
  2866. //                state information and contents into the storage unit passed in.
  2867. //------------------------------------------------------------------------------
  2868. SOM_Scope    void
  2869. SOMLINK        PictureViewer__CloneInto
  2870.              (
  2871.                 SampleCode_PictureViewer*        somSelf,
  2872.                 Environment*                    ev,
  2873.                 ODDraftKey                        key,
  2874.                 ODStorageUnit*                    destinationSU,
  2875.                 ODFrame*                        initiatingFrame
  2876.             )
  2877. {
  2878.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  2879.     SampleCode_PictureViewerMethodDebug("PictureViewer","CloneInto");
  2880.  
  2881.     SOM_TRY    
  2882.         // This calls back up to the persistent object parent class
  2883.         // which copies over our timedate stamp and last modified info.
  2884.         SampleCode_PictureViewer_parent_ODPart_CloneInto(somSelf,ev, key, destinationSU, initiatingFrame);
  2885.     
  2886.         // If we haven't written out to this storage unit, externalize the
  2887.         // current state and contents.
  2888.         
  2889.         if ( !destinationSU->Exists(ev, kODPropContents, gGlobals->fPictScrapKind, 0) )
  2890.         {
  2891.             // Add the properties we need to successfully externalize
  2892.             // ourselves into the destination storage unit.
  2893.             somSelf->CheckAndAddProperties(ev, destinationSU);
  2894.                     
  2895.             // Write out the part's state information.
  2896.             somSelf->ExternalizeStateInfo(ev, destinationSU, key, initiatingFrame);
  2897.  
  2898.             // Write out the part's content.
  2899.             somSelf->ExternalizeContent(ev, destinationSU, key, initiatingFrame);
  2900.         }
  2901.     SOM_CATCH_ALL
  2902.     SOM_ENDTRY
  2903. }
  2904.  
  2905. //------------------------------------------------------------------------------
  2906. // Method:        HandleEvent
  2907. // Origin:        ODPart
  2908. //
  2909. // Description:    The method is called when an event occurs within one of
  2910. //                our owned foci. The exception to this case are "mouse 
  2911. //                movement" events and embedded frame events, which can occur
  2912. //                when a part owns no foci.
  2913. //
  2914. //                The part returns true if the event was handled.
  2915. //------------------------------------------------------------------------------
  2916. SOM_Scope    ODBoolean
  2917. SOMLINK        PictureViewer__HandleEvent
  2918.             (
  2919.                 SampleCode_PictureViewer*        somSelf,
  2920.                 Environment*                    ev,
  2921.                 ODEventData*                    event,
  2922.                 ODFrame*                        frame,
  2923.                 ODFacet*                        facet,
  2924.                 ODEventInfo*                    eventInfo
  2925.             )
  2926. {
  2927.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  2928.     SampleCode_PictureViewerMethodDebug("PictureViewer","HandleEvent");
  2929.  
  2930.     ODBoolean    eventHandled = kODFalse;
  2931.  
  2932.     // Event handling is basically the same as standard Macintosh applications,
  2933.     // except that the events have been renamed for cross-platform compatability.
  2934.  
  2935.     SOM_TRY    
  2936.         switch(event->what)
  2937.         {
  2938.             case kODEvtMouseDown:
  2939.             case kODEvtMouseUp:
  2940.                 eventHandled = somSelf->HandleMouseEvent(ev, event, facet, eventInfo);
  2941.                 break;
  2942.                 
  2943.             case kODEvtMenu:
  2944.                 eventHandled = somSelf->HandleMenuEvent(ev, event, frame);
  2945.                 break;
  2946.     
  2947.             case kODEvtActivate:
  2948.                 // We are being notified that a window we are displayed in has
  2949.                 // just been activated/deactivated (hilighted/unhilighted).
  2950.                 somSelf->WindowActivating(ev, frame, (event->modifiers & activeFlag));
  2951.                 eventHandled = kODTrue;
  2952.                 break;
  2953.         
  2954.             case kODEvtMouseEnter:
  2955.             case kODEvtMouseLeave:
  2956.                 SetCursor(&ODQDGlobals.arrow);
  2957.                 eventHandled = kODTrue;
  2958.                 break;
  2959.     
  2960.             case kODEvtMouseWithin:
  2961.                 eventHandled = kODTrue;
  2962.                 break;
  2963.     
  2964.             // Other events a part might handle:
  2965.             case kODEvtNull:
  2966.             case kODEvtMouseDownEmbedded:
  2967.             case kODEvtMouseUpEmbedded:
  2968.             case kODEvtMouseDownBorder:
  2969.             case kODEvtMouseUpBorder:
  2970.             case kODEvtWindow:
  2971.             case kODEvtKeyUp:
  2972.             case kODEvtKeyDown:
  2973.             case kODEvtAutoKey:
  2974.             case kODEvtDisk:
  2975.             case kODEvtOS:
  2976.             default:
  2977.                 break;
  2978.         }
  2979.     SOM_CATCH_ALL
  2980.     SOM_ENDTRY
  2981.  
  2982.     return eventHandled;
  2983. }
  2984.  
  2985. //------------------------------------------------------------------------------
  2986. // Method:        AdjustMenus
  2987. // Origin:        ODPart
  2988. //
  2989. // Description:    This method is called when a kODEvtMouseDown event occurs in
  2990. //                the menubar and when the part owns the "menu" focus, or when
  2991. //                the root part of a document.
  2992. //
  2993. //                The part first verifies that the base menubar has not been
  2994. //                modified, then enables the menu items and changes their names
  2995. //                where appropriate (eg. About PictureViewer ...).
  2996. //
  2997. //                Within this method, we request the clipboard focus.
  2998. //                If granted, the part can enable the appropriate Edit
  2999. //                menu items. Parts may retain the clipboard focus while 
  3000. //                active, but must be prepared to relinquish it when 
  3001. //                background parts want to inspect it.
  3002. //                Parts must also relinquish the clipboard focus in their 
  3003. //                DisplayFrameRemoved/DisplayFrameClosed methods.
  3004. //------------------------------------------------------------------------------
  3005. SOM_Scope    void
  3006. SOMLINK        PictureViewer__AdjustMenus
  3007.             (
  3008.                 SampleCode_PictureViewer*        somSelf,
  3009.                 Environment*                    ev,
  3010.                 ODFrame*                        frame
  3011.             )
  3012. {
  3013.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  3014.     SampleCode_PictureViewerMethodDebug("PictureViewer","AdjustMenus");
  3015.  
  3016.     ODBoolean    frameIsRoot = frame->IsRoot(ev);
  3017.  
  3018.     if ( frameIsRoot )
  3019.     {
  3020.         // The menubar object always calls the root part's AdjustMenus method before
  3021.         // calling the menu focus owner's. Because of this, we need to validate the
  3022.         // menubar in the case where we are the root part.
  3023.         // We are required to re-validate the menubar before displaying it because
  3024.         // any part could sway the base menubar at any time.
  3025.         if ( gGlobals->fMenuBar->IsValid(ev) == kODFalse )
  3026.             somSelf->InitializeMenuBar(ev);
  3027.     }
  3028.  
  3029.     if ( _fPicture )
  3030.     {
  3031.         gGlobals->fMenuBar->EnableCommand(ev, kODCommandCopy, kODTrue);
  3032.         gGlobals->fMenuBar->EnableCommand(ev, kCommandCrop, kODTrue);
  3033.         gGlobals->fMenuBar->EnableCommand(ev, kCommandScale, kODTrue);
  3034.  
  3035.         // Check the appropriate menu item according to the picture's display mode.
  3036.         if ( _fDisplayMode == kCommandCrop )
  3037.         {
  3038.             gGlobals->fMenuBar->CheckCommand(ev, kCommandCrop, kODTrue);
  3039.             gGlobals->fMenuBar->CheckCommand(ev, kCommandScale, kODFalse);
  3040.         }
  3041.         else
  3042.         {
  3043.             gGlobals->fMenuBar->CheckCommand(ev, kCommandCrop, kODFalse);
  3044.             gGlobals->fMenuBar->CheckCommand(ev, kCommandScale, kODTrue);
  3045.         }
  3046.         
  3047.         if ( !frameIsRoot )
  3048.         {
  3049.             // Enable the "View In Window" command if the frame is not the
  3050.             // root frame of the window and if a picture exists.
  3051.             gGlobals->fMenuBar->EnableCommand(ev, kODCommandViewAsWin, !frameIsRoot);
  3052.         }
  3053.     }
  3054.     else
  3055.     {
  3056.         gGlobals->fMenuBar->EnableCommand(ev, kODCommandCopy, kODFalse);
  3057.         gGlobals->fMenuBar->EnableCommand(ev, kCommandCrop, kODFalse);
  3058.         gGlobals->fMenuBar->EnableCommand(ev, kCommandScale, kODFalse);
  3059.     }
  3060.     
  3061.     TRY
  3062.         ODArbitrator* arbitrator = ODGetSession(ev, _fSelf)->GetArbitrator(ev);
  3063.         TempODFrame menuOwner = arbitrator->AcquireFocusOwner(ev, gGlobals->fMenuFocus);
  3064.     
  3065.         // There is no need to load a resource, create an ODIText object, set the menubar,
  3066.         // and cleanup, if we don't own the menu focus.
  3067.         if ( ODObjectsAreEqual(ev, frame, menuOwner) )
  3068.         {
  3069.             Str63 text;
  3070.             
  3071.             // Get the "about" string from our library's resources.
  3072.             // (note: ODGetIndString focuses the resource fork for us)
  3073.             ODGetIndString(text, kMenuStringResID, kAboutTextID);
  3074.             // Create an IText object to pass into the menubar.
  3075.             TempODIText    menuItem(CreateIText(gGlobals->fEditorScript, gGlobals->fEditorLanguage,
  3076.                                     (StringPtr)&text));
  3077.             // Change the "About" menu item text for our part.
  3078.             gGlobals->fMenuBar->SetItemString(ev, kODCommandAbout, menuItem);
  3079.         }
  3080.     CATCH_ALL
  3081.         // consume the exception, so don't set the ev parameter
  3082.     ENDTRY
  3083. }
  3084.  
  3085. //------------------------------------------------------------------------------
  3086. // Method:        HandleMenuEvent
  3087. // Origin:        PictureViewer
  3088. //
  3089. // Description:    This method is called by the part when a menu event is
  3090. //                received.
  3091. //
  3092. //                Using the menu bar object, we determine what the menu
  3093. //                command is, and call the appropriate method to handle it.
  3094. //------------------------------------------------------------------------------
  3095. SOM_Scope    ODBoolean
  3096. SOMLINK        PictureViewer__HandleMenuEvent
  3097.             (
  3098.                 SampleCode_PictureViewer*        somSelf,
  3099.                 Environment*                    ev,
  3100.                 ODEventData*                    event,
  3101.                 ODFrame*                        frame
  3102.             )
  3103. {
  3104.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  3105.     SampleCode_PictureViewerMethodDebug("PictureViewer","HandleMenuEvent");
  3106.  
  3107.     ODULong        menuResult    = event->message;
  3108.     ODUShort    menu        = HiWord(menuResult);
  3109.     ODUShort    item        = LoWord(menuResult);
  3110.     ODBoolean    result        = kODFalse;
  3111.  
  3112.     SOM_TRY
  3113.         switch( gGlobals->fMenuBar->GetCommand(ev, menu, item) )
  3114.         {
  3115.             case kODCommandAbout:    
  3116.                 somSelf->HandleDialogBox(ev, frame, kAboutBoxID, 0);
  3117.                 result = kODTrue;
  3118.                 break;
  3119.     
  3120.             case kODCommandCopy:
  3121.                 somSelf->HandleCopy(ev, frame);
  3122.                 result = kODTrue;
  3123.                 break;
  3124.     
  3125.             case kODCommandViewAsWin:
  3126.                 somSelf->Open(ev, frame);
  3127.                 result = kODTrue;
  3128.                 break;
  3129.     
  3130.             case kCommandCrop:
  3131.                 somSelf->HandleDisplayMenuCommand(ev, kCommandCrop, frame);
  3132.                 result = kODTrue;
  3133.                 break;
  3134.                 
  3135.             case kCommandScale:
  3136.                 somSelf->HandleDisplayMenuCommand(ev, kCommandScale, frame);
  3137.                 result = kODTrue;
  3138.                 break;
  3139.     
  3140.             default:
  3141.                 result = kODFalse;
  3142.                 break;
  3143.         }
  3144.         
  3145.     SOM_CATCH_ALL
  3146.     SOM_ENDTRY
  3147.  
  3148.     return result;
  3149. }
  3150.  
  3151. //------------------------------------------------------------------------------
  3152. // Method:        HandleMouseEvent
  3153. // Origin:        PictureViewer
  3154. //
  3155. // Description:    This method is called by the part when a mouse event
  3156. //                is received.
  3157. //
  3158. //                A typical part would determine the event type (up/down)
  3159. //                and respond appropriately, but we have no "real"
  3160. //                content model, so we activate the part as appropriate
  3161. //                and call a generic method to handle the event.
  3162. //
  3163. // Remember:    When a frame is inactive, the first mouse up event
  3164. //                should activate it; inactive frames do not recieve
  3165. //                kODEvtMouseDown events.
  3166. //------------------------------------------------------------------------------
  3167. SOM_Scope    ODBoolean
  3168. SOMLINK        PictureViewer__HandleMouseEvent
  3169.             (
  3170.                 SampleCode_PictureViewer*        somSelf,
  3171.                 Environment*                    ev,
  3172.                 ODEventData*                    event,
  3173.                 ODFacet*                        facet,
  3174.                 ODEventInfo*                    eventInfo
  3175.             )
  3176. {
  3177.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  3178.     SampleCode_PictureViewerMethodDebug("PictureViewer","HandleMouseEvent");
  3179.  
  3180.     SOM_TRY
  3181.     
  3182.     // If the facet parameter is invalid, the mouse up occurred outside the
  3183.     // bounds of a Modal window, otherwise it should be treated normally.
  3184.     
  3185.     if ( facet != kODNULL )
  3186.     {
  3187.         if ( event->what == kODEvtMouseUp )
  3188.         {
  3189.             ODWindow* window = facet->GetWindow(ev);
  3190.  
  3191.             // Activate inactive windows on the first mouse up event.
  3192.             if ( !window->IsActive(ev) )
  3193.             {
  3194.                 window->Select(ev);
  3195.             }
  3196.             else
  3197.             {
  3198.                 // Activate the frame (if needed) on all subsequent 
  3199.                 // mouse up events.                
  3200.                 ODFrame* frame = facet->GetFrame(ev);
  3201.                 
  3202.                 // Get our state information from the PartInfo of the frame.
  3203.                 CFrameInfo* frameInfo = (CFrameInfo*)frame->GetPartInfo(ev);
  3204.                 
  3205.                 // If this frame is not the active one, activate it by
  3206.                 // requesting the appropriate foci.
  3207.     
  3208.                 if ( !frameInfo->IsFrameActive() )
  3209.                 {
  3210.                     if ( somSelf->ActivateFrame(ev, frame) )
  3211.                     {
  3212.                         // Keep track of which facet was the last active for
  3213.                         // positioning part windows.
  3214.                         frameInfo->SetActiveFacet(facet);
  3215.                     }
  3216.                     else
  3217.                     {
  3218.                         // We were unsuccessful in activating our frame.
  3219.                         return kODFalse;
  3220.                     }
  3221.                 }
  3222.             }
  3223.         }
  3224.         else if ( event->what == kODEvtMouseDown )                
  3225.         {
  3226.             // This is where the mouse down event is handled.
  3227.         }
  3228.     }
  3229.     else
  3230.     {
  3231.         // User clicked outside the bounds of a Modal window.
  3232.         SysBeep(1);
  3233.     }
  3234.  
  3235.     SOM_CATCH_ALL
  3236.     SOM_ENDTRY
  3237.     
  3238.     return kODTrue;
  3239. }
  3240.  
  3241. //------------------------------------------------------------------------------
  3242. // Method:        PartActivated
  3243. // Origin:        PictureViewer
  3244. //
  3245. // Description:    This method is called when the part has successfully acquired
  3246. //                the set of foci which allow it to run.
  3247. //------------------------------------------------------------------------------
  3248. SOM_Scope    void
  3249. SOMLINK        PictureViewer__PartActivated
  3250.               (
  3251.                  SampleCode_PictureViewer*        somSelf,
  3252.                  Environment*                    ev,
  3253.                  ODFrame*                        frame
  3254.             )
  3255. {
  3256.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  3257.     SampleCode_PictureViewerMethodDebug("PictureViewer","PartActivated");
  3258.  
  3259.     SOM_TRY
  3260.         // We are required to re-validate the menubar before displaying it
  3261.         // because any part can sway the base menubar at any time.
  3262.         if ( gGlobals->fMenuBar->IsValid(ev) == kODFalse )
  3263.             somSelf->InitializeMenuBar(ev);
  3264.     
  3265.         // Display our menu bar.
  3266.         gGlobals->fMenuBar->Display(ev);
  3267.         
  3268.         // And set our "active" state.
  3269.         CFrameInfo* frameInfo = (CFrameInfo*)frame->GetPartInfo(ev);
  3270.         frameInfo->SetFrameActive(kODTrue);
  3271.     SOM_CATCH_ALL
  3272.     SOM_ENDTRY
  3273. }
  3274.  
  3275. //------------------------------------------------------------------------------
  3276. // Method:        ActivateFrame
  3277. // Origin:        PictureViewer
  3278. //
  3279. // Description:    This method is called by the part when a kODEvtMouseUp
  3280. //                occurs in an inactive frame in an active window, and 
  3281. //                when an OpenDoc document comes forward.
  3282. //
  3283. //                The part activates the frame by requesting the menu
  3284. //                focus and by calling FocusAcquired if we were successful.
  3285. //                The method returns true if no problems were encountered as
  3286. //                a signal to the caller that the frame is now active.
  3287. //------------------------------------------------------------------------------
  3288. SOM_Scope    ODBoolean
  3289. SOMLINK        PictureViewer__ActivateFrame
  3290.              (
  3291.                 SampleCode_PictureViewer*        somSelf,
  3292.                 Environment*                    ev,
  3293.                 ODFrame*                        frame
  3294.             )
  3295. {
  3296.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  3297.     SampleCode_PictureViewerMethodDebug("PictureViewer","ActivateFrame");
  3298.  
  3299.     ODBoolean    activated = kODFalse;
  3300.     
  3301.     SOM_TRY
  3302.         // Request the set of foci necessary to become active.
  3303.         if ( ODGetSession(ev, _fSelf)->GetArbitrator(ev)
  3304.                     ->RequestFocusSet(ev, gGlobals->fUIFocusSet, frame) )
  3305.         {
  3306.             // Activate the part.
  3307.             somSelf->PartActivated(ev, frame);
  3308.             // We were able to become active.
  3309.             activated = kODTrue;
  3310.         }
  3311.     SOM_CATCH_ALL
  3312.     SOM_ENDTRY
  3313.     
  3314.     // Let our caller know we succeded or failed.
  3315.     return activated;
  3316. }
  3317.  
  3318. //------------------------------------------------------------------------------
  3319. // Method:        WindowActivating
  3320. // Origin:        PictureViewer
  3321. //
  3322. // Description:    This method is called by the part when a window activation
  3323. //                event (kODEvtActivate) occurs.
  3324. //
  3325. //                The part remembers the frame's active state and restores it when
  3326. //                events come in. If the frame is active and the window is being
  3327. //                sent into the background, remember to reactivate the part when
  3328. //                the window is reactivated.
  3329. //------------------------------------------------------------------------------
  3330. SOM_Scope    void
  3331. SOMLINK        PictureViewer__WindowActivating
  3332.              (
  3333.                 SampleCode_PictureViewer*    somSelf,
  3334.                 Environment*                ev,
  3335.                 ODFrame*                    frame,
  3336.                 ODBoolean                    activating
  3337.             )
  3338. {
  3339.     SampleCode_PictureViewerMethodDebug("PictureViewer","WindowActivating");
  3340.  
  3341.     SOM_TRY
  3342.     
  3343.         CFrameInfo* frameInfo = (CFrameInfo*)frame->GetPartInfo(ev);
  3344.         
  3345.         // The window is being activated and we had the selection focus when
  3346.         // the window was deactivated, so activate ourself.
  3347.         if ( activating && frameInfo->FrameNeedsReactivating() )
  3348.         {
  3349.             // The window is being activated, so acquire our foci.
  3350.             if (somSelf->ActivateFrame(ev, frame))
  3351.                 frameInfo->SetFrameReactivate(kODFalse);
  3352.         }
  3353.         else if ( !activating && frameInfo->IsFrameActive() )
  3354.         {
  3355.             // The window is being deactivated and we have the active part.
  3356.             // So give up our foci and remind ourselves that we need to request
  3357.             // the focus when the window is reactivated.
  3358.             
  3359.             frameInfo->SetFrameReactivate(kODTrue);
  3360.         }
  3361.  
  3362.     SOM_CATCH_ALL
  3363.     SOM_ENDTRY
  3364. }
  3365.  
  3366. //------------------------------------------------------------------------------
  3367. // Method:        AcquireFramesWindow
  3368. // Origin:        PictureViewer
  3369. //
  3370. // Description:    This method is called by the part when a frame that has been
  3371. //                previously opened is being opened again.
  3372. //                The method retrieves the existing window for the frame
  3373. //                and returns it.                
  3374. //------------------------------------------------------------------------------
  3375. SOM_Scope    ODWindow*
  3376. SOMLINK        PictureViewer__AcquireFramesWindow
  3377.             (
  3378.                 SampleCode_PictureViewer*    somSelf, 
  3379.                 Environment*                ev,
  3380.                 ODFrame*                     frame
  3381.             )
  3382. {
  3383.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  3384.     SampleCode_PictureViewerMethodDebug("PictureViewer","AcquireFramesWindow");
  3385.  
  3386.     ODWindow*    window = kODNULL;
  3387.  
  3388.     SOM_TRY
  3389.         CFrameInfo*    frameInfo = (CFrameInfo*)frame->GetPartInfo(ev);
  3390.         ODWindow* window = frameInfo->AcquirePartWindow(ev);
  3391.     SOM_CATCH_ALL
  3392.     SOM_ENDTRY
  3393.  
  3394.     return window;
  3395. }
  3396.  
  3397. //------------------------------------------------------------------------------
  3398. // Method:        CreateWindow
  3399. // Origin:        PictureViewer
  3400. //
  3401. // Description:    This method is called by the part when a window is
  3402. //                being opened on a frame.
  3403. //
  3404. //                The part determines the new window's name, position,
  3405. //                and size, and creates a Macintosh document window. The
  3406. //                part registers the window with OpenDoc to facilitate
  3407. //                the creation of a window object and the root frame for
  3408. //                the window.
  3409. //------------------------------------------------------------------------------
  3410. SOM_Scope    ODWindow*
  3411. SOMLINK        PictureViewer__CreateWindow
  3412.             (
  3413.                 SampleCode_PictureViewer        *somSelf,
  3414.                 Environment                        *ev,
  3415.                 ODFrame*                        frame,
  3416.                 ODType                            frameType,
  3417.                 WindowProperties*                windowProperties
  3418.             )
  3419. {
  3420.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  3421.     SampleCode_PictureViewerMethodDebug("PictureViewer","CreateWindow");
  3422.  
  3423.     ODPlatformWindow    platformWindow    = kODNULL;
  3424.     ODWindow*            window            = kODNULL;
  3425.  
  3426.     ODVolatile(platformWindow);    
  3427.     ODVolatile(window);
  3428.  
  3429.     SOM_TRY
  3430.         // Using the name and the calculated rectangle, create a new window.
  3431.         // Note that we are allocating the window record in temp mem using
  3432.         // the OpenDoc memory mgr. This helps reduce app heap usage.
  3433.         // In addition, OpenDoc requires that all new windows be initially
  3434.         // hidden so that it can correctly layer windows/palettes.
  3435.         platformWindow = NewCWindow((Ptr)ODNewPtr(sizeof(WindowRecord)),
  3436.                                     &(windowProperties->boundsRect),
  3437.                                     windowProperties->title,
  3438.                                     kODFalse,                 /* visible */
  3439.                                     windowProperties->procID,
  3440.                                     (WindowPtr)-1L,
  3441.                                     windowProperties->hasCloseBox,
  3442.                                     windowProperties->refCon);
  3443.  
  3444.         if ( platformWindow )
  3445.         {
  3446.             ODWindowState* windowState = _fSession->GetWindowState(ev);
  3447.             
  3448.             // Shoud the window be saved in the document? Yes if the root frame is
  3449.             // persistent.
  3450.             ODBoolean saveWindow = ODISOStrEqual(frameType, kODFrameObject);
  3451.             
  3452.             // Tell the window object that we will be disposing the window record
  3453.             // when the root frame is closed/removed.
  3454.             ODBoolean shouldDispose = kODFalse;
  3455.             
  3456.             // Determine whether we are creating a new window (frame is null),
  3457.             // or opening a previously saved window (frame is valid).
  3458.             
  3459.             if ( frame == kODNULL )
  3460.             {                                
  3461.                 // Tell OpenDoc about it by creating an OpenDoc window object.
  3462.                 window = windowState->
  3463.                             RegisterWindow(ev, 
  3464.                                 platformWindow,                    // Macintosh WindowPtr
  3465.                                 frameType,                        // Frame type (Persistent/Non-persistent)
  3466.                                 windowProperties->isRootWindow,    // Is this a document window?
  3467.                                 windowProperties->isResizable,    // Is this window resizeable?
  3468.                                 windowProperties->isFloating,    // Is this window floating?
  3469.                                 saveWindow,                        // Should this window be persistent?
  3470.                                 shouldDispose,                    // (see comment above)
  3471.                                 _fSelf,                            // Part reference to us
  3472.                                 gGlobals->fFrameView,            // What view should the window have?
  3473.                                 gGlobals->fMainPresentation,    // What presentation should the window have?
  3474.                                 windowProperties->sourceFrame);    // The display frame being opened, if any
  3475.             }
  3476.             else
  3477.             {
  3478.                 // Tell OpenDoc about it by creating an OpenDoc window object.
  3479.                 window = windowState->
  3480.                             RegisterWindowForFrame(ev, 
  3481.                                 platformWindow,                    // Macintosh WindowPtr
  3482.                                 frame,                             // Frame type (Persistent/Non-persistent)
  3483.                                 windowProperties->isRootWindow,    // Is this a document window?
  3484.                                 windowProperties->isResizable,    // Is this window resizeable?
  3485.                                 windowProperties->isFloating,    // Is this window floating?
  3486.                                 saveWindow,                        // Should this window be persistent?
  3487.                                 shouldDispose,                    // (see comment above)
  3488.                                 windowProperties->sourceFrame);    // The display frame being opened, if any
  3489.             }
  3490.         }
  3491.  
  3492.     SOM_CATCH_ALL
  3493.         // Clean up windows.
  3494.         CloseWindow(platformWindow);
  3495.         ODDisposePtr(platformWindow);
  3496.         ODReleaseObject(ev, window);
  3497.         
  3498.         // Get the right error message for the problem.
  3499.         ODSShort errMsgNum = (!frame && windowProperties->sourceFrame)
  3500.                             ? kErrCantOpenPartWindow : kErrCantOpenDocWindow;
  3501.  
  3502.         // Alert the user of the problem.
  3503.         somSelf->HandleDialogBox(ev, frame, kErrorBoxID, errMsgNum);
  3504.         // Change the error code value so the DocShell doesn't
  3505.         // display an error dialog.
  3506.         SetErrorCode(kODErrAlreadyNotified);
  3507.     SOM_ENDTRY
  3508.     
  3509.     return window;
  3510. }
  3511.  
  3512. //------------------------------------------------------------------------------
  3513. // Method:        CalcPartWindowSize
  3514. // Origin:        PictureViewer
  3515. //
  3516. // Description:    This method is called by the part to determine what
  3517. //                size a new window shoud be.
  3518. //------------------------------------------------------------------------------
  3519. SOM_Scope    Rect
  3520. SOMLINK        PictureViewer__CalcPartWindowSize
  3521.              (
  3522.                 SampleCode_PictureViewer*    somSelf,
  3523.                 Environment*                ev,
  3524.                 ODFrame*                    /*sourceFrame*/
  3525.             )
  3526. {
  3527.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  3528.     SampleCode_PictureViewerMethodDebug("PictureViewer","CalcPartWindowSize");
  3529.  
  3530.     const ODSShort kOnePageWidth = 600;
  3531.     
  3532.     Rect    windowRect;
  3533.  
  3534.     SOM_TRY
  3535.     
  3536.     // If a source frame is given, the part is being asked to open one of
  3537.     // its display frames into a part window. Otherwise, we are being opened
  3538.     // as the root frame of the current document and should size the window
  3539.     // accordingly.
  3540.     if ( _fPicture )
  3541.     {
  3542.         // Set up the window's size to be that of the picture being displayed.
  3543.         windowRect = (**((PicHandle)_fPicture)).picFrame;
  3544.     
  3545.         OffsetRect(&windowRect, -windowRect.left, -windowRect.top);
  3546.     
  3547.         // Add space for the scrollbars
  3548.         windowRect.bottom += kScrollBarSize;
  3549.         windowRect.right += kScrollBarSize;
  3550.     }
  3551.     else
  3552.     {
  3553.         // Otherwise, just open a large window.
  3554.         SetRect(&windowRect, 0, 0,
  3555.                   ODQDGlobals.screenBits.bounds.right - (3 * kODLargeIconSize),
  3556.                   ODQDGlobals.screenBits.bounds.bottom
  3557.                       - GetMBarHeight() - kMacWindowTitleBarHeight - kALittleNudge);        
  3558.         
  3559.         if (windowRect.right - windowRect.left > kOnePageWidth)
  3560.             windowRect.right = windowRect.left + kOnePageWidth;
  3561.     }
  3562.     
  3563.     SOM_CATCH_ALL
  3564.     SOM_ENDTRY
  3565.     
  3566.     return windowRect;
  3567. }
  3568.  
  3569. //------------------------------------------------------------------------------
  3570. // Method:        CalcPartWindowPosition
  3571. // Origin:        PictureViewer
  3572. //
  3573. // Description:    This method is called by the part to determine where
  3574. //                to align the new window (top left corner of the screen
  3575. //                or tiled to a frame).
  3576. //------------------------------------------------------------------------------
  3577. SOM_Scope    Rect
  3578. SOMLINK        PictureViewer__CalcPartWindowPosition
  3579.              (
  3580.                 SampleCode_PictureViewer*    somSelf,
  3581.                 Environment*                ev,
  3582.                 ODFrame*                    frame,
  3583.                 Rect*                        partWindowBounds
  3584.             )
  3585. {
  3586.     SampleCode_PictureViewerMethodDebug("PictureViewer","CalcPartWindowPosition");
  3587.  
  3588.     ODFacet*            activeFacet;
  3589.     ODShape*            frameShape;
  3590.     ODRect                bbox;
  3591.     Rect                bounds;
  3592.     
  3593.     SOM_TRY
  3594.     
  3595.     // We need to know which facet of the frame we are opening to position
  3596.     // the part window.
  3597.     activeFacet = somSelf->GetActiveFacetForFrame(ev, frame);
  3598.     
  3599.     // This should never occur, but if it did, it would be fatal.
  3600.     // So we will just pass back the same rectangle.
  3601.     if ( activeFacet == kODNULL )
  3602.         return *partWindowBounds;
  3603.     
  3604.     // For the purposes of tiling, we need the to know the area of the
  3605.     // document the frame occupies. We do this by getting the bouding
  3606.     // box and offsetting it by the aggregate external window transform
  3607.     // of the facet.
  3608.     
  3609.     frameShape = activeFacet->GetFrame(ev)->AcquireFrameShape(ev, kODNULL);
  3610.     TempODTransform windowFrameTransform = activeFacet->AcquireWindowFrameTransform(ev, kODNULL);
  3611.     TempODShape boundsShape = ODCopyAndRelease(ev, frameShape);
  3612.  
  3613.     // Translate the bounds rect into window coordinates.
  3614.     boundsShape->Transform(ev, windowFrameTransform);
  3615.     
  3616.     // Get and convert the bounding box into a QuickDraw rectangle.
  3617.     boundsShape->GetBoundingBox(ev, &bbox);
  3618.     FixedToIntRect(bbox, bounds);
  3619.         
  3620.     // We then call our method to tile the part window.
  3621.     *partWindowBounds = TilePartWindow(ev, &bounds, partWindowBounds);
  3622.     
  3623.     // Set the port and origin so we can convert the rect to
  3624.     // global Window Mgr coordinates.
  3625.     SetPort(activeFacet->GetCanvas(ev)->GetQDPort(ev));
  3626.     SetOrigin(0,-kMacWindowTitleBarHeight);
  3627.     
  3628.     // Convert the local coordinates to global Window Mgr coordinates.
  3629.     LocalToGlobal((Point*)&partWindowBounds->top);
  3630.     LocalToGlobal((Point*)&partWindowBounds->bottom);
  3631.     
  3632.     SOM_CATCH_ALL
  3633.     SOM_ENDTRY
  3634.     
  3635.     return *partWindowBounds;
  3636. }
  3637.  
  3638. //------------------------------------------------------------------------------
  3639. // Method:            HandleCopy
  3640. // Origin:            PictureViewer
  3641. //
  3642. //    Description:    This method is called in response to the user
  3643. //                    selecting the Copy command. A promise is written
  3644. //                    out to the clipboard's storage unit, and is
  3645. //                    fulfilled later upon request.
  3646. //------------------------------------------------------------------------------
  3647. SOM_Scope    void
  3648. SOMLINK        PictureViewer__HandleCopy
  3649.             (
  3650.                   SampleCode_PictureViewer*        somSelf,
  3651.                   Environment*                    ev,
  3652.                   ODFrame*                        frame
  3653.              )
  3654. {
  3655.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  3656.     SampleCode_PictureViewerMethodDebug("PictureViewer","HandleCopy");
  3657.     
  3658.     ODClipboard*    clipboard     = _fSession->GetClipboard(ev);
  3659.     
  3660.     // Remove any existing data on the clipboard.
  3661.     clipboard->Clear(ev);
  3662.  
  3663.     ODStorageUnit*    clipboardSU = clipboard->GetContentStorageUnit(ev);
  3664.     ODDraft*        srcDraft     = ODGetDraft(ev, _fSelf);
  3665.     ODDraft*        destDraft     = ODGetDraft(ev, clipboardSU);
  3666.     ODDraftKey        key            = kODNULLKey;
  3667.     
  3668.     ODVolatile(clipboard);
  3669.     ODVolatile(srcDraft);
  3670.     ODVolatile(key);
  3671.  
  3672.     SOM_TRY
  3673.         // Any modifications to the clipboard should be within BeginClone/EndClone
  3674.         key = srcDraft->BeginClone(ev, destDraft, frame, kODCloneCopy);
  3675.     
  3676.         // Annotate the clipboard with the frame shape.    
  3677.         TempODShape frameShape = frame->AcquireFrameShape(ev, kODNULL);
  3678.         clipboardSU->AddProperty(ev, kODPropSuggestedFrameShape);
  3679.         frameShape->WriteShape(ev, clipboardSU);
  3680.                             
  3681.         ODByteArray    data;
  3682.         data._maximum = 0;
  3683.         data._length = 0;
  3684.         data._buffer = kODNULL;
  3685.     
  3686.         // Add the content property and promised value.
  3687.         clipboardSU->AddProperty(ev, kODPropContents);
  3688.         clipboardSU->SetPromiseValue(ev, gGlobals->fPictScrapKind, 0,  &data, _fSelf);
  3689.         
  3690.         // Complete the clone transaction
  3691.         srcDraft->EndClone(ev, key);
  3692.         
  3693.     SOM_CATCH_ALL
  3694.         if ( key != kODNULLKey )
  3695.             srcDraft->AbortClone(ev, key);
  3696.         clipboard->Clear(ev);
  3697.     SOM_ENDTRY
  3698. }
  3699.  
  3700. //------------------------------------------------------------------------------
  3701. // Method:        HandleDisplayMenuCommand
  3702. // Origin:        PictureViewer
  3703. //
  3704. // Description:    Checks the appropriate menuitem in our Display menu.
  3705. //------------------------------------------------------------------------------
  3706. SOM_Scope    void
  3707. SOMLINK        PictureViewer__HandleDisplayMenuCommand
  3708.             (
  3709.                 SampleCode_PictureViewer*        somSelf,
  3710.                 Environment*                    ev,
  3711.                 ODSLong                            command,
  3712.                 ODFrame*                        frame
  3713.             )
  3714. {
  3715.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  3716.     SampleCode_PictureViewerMethodDebug("PictureViewer","HandleDisplayMenuCommand");
  3717.     
  3718.     SOM_TRY
  3719.     
  3720.         if ( _fPicture )
  3721.         {
  3722.             if ( _fDisplayMode != command )
  3723.             {
  3724.                 gGlobals->fMenuBar->CheckCommand(ev, command, kODTrue);
  3725.                 gGlobals->fMenuBar->CheckCommand(ev, _fDisplayMode, kODFalse);
  3726.                 _fDisplayMode = command;
  3727.                 
  3728.                 frame->Invalidate(ev, kODNULL, kODNULL);        
  3729.     
  3730.                 // Change the source frame of this frame, if one exists, to match
  3731.                 // the new view setting.
  3732.                 CFrameInfo* frameInfo = (CFrameInfo*)frame->GetPartInfo(ev);
  3733.                 if ( frameInfo->HasSourceFrame() )
  3734.                 {
  3735.                     ODFrame* sourceFrame = frameInfo->GetSourceFrame(ev);
  3736.                     sourceFrame->Invalidate(ev, kODNULL, kODNULL);        
  3737.                 }
  3738.         
  3739.                 // Change the dependent frame, if one exists, to match
  3740.                 // the new view setting.
  3741.                 if ( frameInfo->HasDependentFrame() )
  3742.                 {
  3743.                     ODFrame* displayFrame = frameInfo->GetDependentFrame(ev);
  3744.                     displayFrame->Invalidate(ev, kODNULL, kODNULL);        
  3745.                 }
  3746.             }
  3747.         }
  3748.         
  3749.     SOM_CATCH_ALL
  3750.     SOM_ENDTRY
  3751. }
  3752.  
  3753. //------------------------------------------------------------------------------
  3754. // Method:        HandleDialogBox
  3755. // Origin:        PictureViewer
  3756. //
  3757. // Description:    This method is called by the part when a dialog needs to be
  3758. //                displayed (eg. the About Box). If a valid error number is
  3759. //                passed in, an error dialog will be displayed.
  3760. //------------------------------------------------------------------------------
  3761. SOM_Scope    void
  3762. SOMLINK        PictureViewer__HandleDialogBox
  3763.             (    
  3764.                 SampleCode_PictureViewer*    somSelf,
  3765.                 Environment*                ev,
  3766.                 ODFrame*                     frame,
  3767.                 ODSShort                     dialogID,
  3768.                 ODUShort                     errorNumber
  3769.             )
  3770. {
  3771.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  3772.     SampleCode_PictureViewerMethodDebug("PictureViewer","HandleDialogBox");
  3773.     
  3774.     ODFrame* focusFrame = frame;
  3775.     
  3776.     SOM_TRY
  3777.     
  3778.     // If the calling method does not have a frame available to it, we need to
  3779.     // locate a frame to use for requesting the modal focus. Find the first valid
  3780.     // frame in our display frames list.
  3781.     if ( focusFrame == kODNULL )
  3782.     {
  3783.         CListIterator fiter(_fDisplayFrames);
  3784.         for ( CFrameProxy* proxy = (CFrameProxy*)fiter.First();
  3785.                 fiter.IsNotComplete(); proxy = (CFrameProxy*)fiter.Next() )
  3786.         {
  3787.             if ( proxy->FrameIsLoaded(ev) )
  3788.                 focusFrame = proxy->GetFrame(ev);
  3789.             if ( focusFrame )
  3790.                 break;
  3791.         }
  3792.     }
  3793.     
  3794.     // Our dialog boxes are modal so we must request the Modal focus to prevent
  3795.     // multiple modal dialogs being displayed simultaneously.
  3796.     
  3797.     if ( _fSession->GetArbitrator(ev)->RequestFocus(ev, gGlobals->fModalFocus, focusFrame) )
  3798.     {
  3799.         DialogPtr    dialog;
  3800.         ODSShort    itemHit;
  3801.  
  3802.         // Dim the frontmost document window.
  3803.         _fSession->GetWindowState(ev)->DeactivateFrontWindows(ev);
  3804.  
  3805.         ODSLong savedRef = BeginUsingLibraryResources();
  3806.         {            
  3807.             dialog = GetNewDialog(kAboutBoxID, kODNULL, (WindowPtr) -1L);
  3808.  
  3809.             if ( dialog )
  3810.             {
  3811.                 if ( errorNumber > 0 )
  3812.                 {
  3813.                     Handle    itemHandle;
  3814.                     Rect    itemRect;
  3815.                     short    itemType;
  3816.                     Str255    errStr;
  3817.                     
  3818.                     GetIndString(errStr, kErrorStringResID, errorNumber);
  3819.                     GetDialogItem(dialog, kErrStrFieldID, &itemType, &itemHandle, &itemRect);
  3820.                     SetDialogItemText(itemHandle, errStr);
  3821.                     
  3822.                     // We don't need the cancel button for an error dialog.
  3823.                     HideDialogItem(dialog, cancel);
  3824.  
  3825.                     SetDialogDefaultItem(dialog, ok);
  3826.                 }
  3827.  
  3828.                 SetCursor(&ODQDGlobals.arrow);
  3829.                 ShowWindow(dialog);
  3830.                 ModalDialog(kODNULL, &itemHit);
  3831.                 DisposeDialog(dialog);
  3832.             }
  3833.             else
  3834.             {
  3835.                 // Could not load dialog...something is amiss.
  3836.                 SysBeep(2);
  3837.             }
  3838.         }
  3839.         EndUsingLibraryResources(savedRef);
  3840.         
  3841.         // Inform the Arbitrator that we no longer require the Modal focus.
  3842.         _fSession->GetArbitrator(ev)->RelinquishFocus(ev, gGlobals->fModalFocus, focusFrame);
  3843.         
  3844.         // Highlight the frontmost document window.
  3845.         _fSession->GetWindowState(ev)->ActivateFrontWindows(ev);
  3846.     }
  3847.     else
  3848.     {
  3849.         // If we can't get the modal focus, then another modal dialog is
  3850.         // already being displayed.
  3851.  
  3852.         SysBeep(2);
  3853.     }
  3854.  
  3855.     SOM_CATCH_ALL
  3856.     SOM_ENDTRY
  3857. }
  3858.  
  3859. //------------------------------------------------------------------------------
  3860. // Method:        ReadPictureFile
  3861. // Origin:        PictureViewer
  3862. //
  3863. // Description:    Retrieve the PICT data from an OS file. The data
  3864. //                fork is examined first, and if no PICT data is present,
  3865. //                then search the resource fork.
  3866. //------------------------------------------------------------------------------
  3867. SOM_Scope    void
  3868. SOMLINK        PictureViewer__ReadPictureFile
  3869.                (
  3870.                  SampleCode_PictureViewer*        somSelf,
  3871.                  Environment*                    ev,
  3872.                   ODFacet*                        facet,
  3873.                   HFSFlavor*                        hfsInfo,
  3874.                   ODULong                            pictSize
  3875.               )
  3876. {
  3877.      SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  3878.     SampleCode_PictureViewerMethodDebug("PictureViewer","ReadPictureFile");
  3879.  
  3880.     // We're called when a PICT file is being internalized or dropped.
  3881.  
  3882.     ODBoolean    validPicture = kODFalse;
  3883.     ODHandle     tempPict = kODNULL;
  3884.     FSSpec         fileSpec;
  3885.     ODSShort    refNum;
  3886.     
  3887.     ODVolatile(tempPict);
  3888.     
  3889.     SOM_TRY
  3890.         // First check the data fork for the PICT data
  3891.         fileSpec = hfsInfo->fileSpec;
  3892.  
  3893.         // Open the data fork, and catch any errors.
  3894.         THROW_IF_ERROR( FSpOpenDF(&fileSpec, fsRdPerm, &refNum) );
  3895.  
  3896.         // Account for the 512-byte file header in 'PICT' file.
  3897.         ODSLong fileheader = 512;
  3898.         
  3899.         TRY
  3900.             THROW_IF_ERROR( GetEOF(refNum, (ODSLong*)&pictSize) );
  3901.             THROW_IF_ERROR( SetFPos(refNum, fsFromStart, fileheader) );
  3902.             pictSize -= fileheader;
  3903.     
  3904.             if ( pictSize > 0 )
  3905.             {
  3906.                 tempPict = ODNewHandle(pictSize);
  3907.                 
  3908.                 TRY
  3909.                     TempODHandleLock hLock(tempPict);
  3910.                     THROW_IF_ERROR( FSRead(refNum, (ODSLong*)&pictSize, *hLock) );
  3911.                 CATCH_ALL
  3912.                     ODDisposeHandle(tempPict);
  3913.                     RERAISE;
  3914.                 ENDTRY
  3915.                 
  3916.                 if ( _fPicture != kODNULL )
  3917.                     ODDisposeHandle(_fPicture);
  3918.                         
  3919.                 _fPicture = tempPict;
  3920.                 validPicture = kODTrue;
  3921.         }
  3922.  
  3923.         THROW_IF_ERROR( FSClose(refNum) );
  3924.         CATCH_ALL
  3925.             FSClose(refNum);
  3926.             RERAISE;
  3927.         ENDTRY
  3928.         
  3929.         if ( validPicture == kODFalse )
  3930.         {
  3931.             // Data wasn't present in the data fork, so check
  3932.             // the resource fork.
  3933.             refNum = FSpOpenResFile(&fileSpec, fsRdPerm);
  3934.  
  3935.             if ( refNum == -1 )
  3936.                 THROW(ResError());
  3937.                 
  3938.             TRY
  3939.                 // We use our utility function Read1IndResource to read
  3940.                 // the resource into memory.  We use this rather than just
  3941.                 // calling Get1IndResource because Get1IndResource would
  3942.                 // put the resoure in the application heap, and we don't
  3943.                 // have much room available in the application heap. It also
  3944.                 // detaches the resource from the resource fork it came from.
  3945.                 tempPict = Read1IndResource(kPictureDataType, 1);
  3946.                 if ( tempPict != kODNULL )
  3947.                 {
  3948.                     // If successful, dispose of the existing data and
  3949.                     // replace it with the new.
  3950.                     if ( _fPicture != kODNULL )
  3951.                         ODDisposeHandle(_fPicture);
  3952.  
  3953.                     _fPicture = tempPict;
  3954.                     validPicture = kODTrue;
  3955.                 }
  3956.                 else
  3957.                 {
  3958.                     // An error must have occurred when getting the PICT resource.
  3959.                     // Don't want to throw. Just internalize as nothing.
  3960.                 }
  3961.             
  3962.             CATCH_ALL
  3963.                 if ( tempPict != kODNULL )
  3964.                     ODDisposeHandle(tempPict);
  3965.                 CloseResFile(refNum);
  3966.                 RERAISE;
  3967.             ENDTRY
  3968.             
  3969.             // Close the resource fork.
  3970.             CloseResFile(refNum);
  3971.         }    
  3972.         
  3973.     SOM_CATCH_ALL
  3974.         // Check the validity flag. If false, clear the
  3975.         // ev parameter so we can continue and just
  3976.         // display an empty picture (nothing).
  3977.         if ( !validPicture )
  3978.         {
  3979.             // Make sure our data handle doesn't contain any data.
  3980.             ODDisposeHandle(_fPicture);
  3981.             _fPicture = kODNULL;
  3982.         }
  3983.     SOM_ENDTRY
  3984. }
  3985.  
  3986. //------------------------------------------------------------------------------
  3987. // Method:        SetDirty
  3988. // Origin:        PictureViewer
  3989. //
  3990. // Description:    This method is called by the part when the content or
  3991. //                state of the part has been modified by the user and
  3992. //                the "Save As" menu item should be enabled.
  3993. //------------------------------------------------------------------------------
  3994. SOM_Scope    void
  3995. SOMLINK        PictureViewer__SetDirty
  3996.              (
  3997.                 SampleCode_PictureViewer*        somSelf,
  3998.                 Environment*                    ev
  3999.             )
  4000. {
  4001.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  4002.     SampleCode_PictureViewerMethodDebug("PictureViewer","SetDirty");
  4003.  
  4004.     SOM_TRY
  4005.         // There is no need to repeatedly tell the draft we have changed;
  4006.         // once is sufficient.
  4007.         if ( !_fDirty && !_fReadOnlyStorage )
  4008.         {
  4009.             ODGetDraft(ev, _fSelf)->SetChangedFromPrev(ev);
  4010.             _fDirty = kODTrue;
  4011.         }
  4012.     SOM_CATCH_ALL
  4013.     SOM_ENDTRY
  4014. }
  4015.  
  4016. //------------------------------------------------------------------------------
  4017. // Method:        GenerateThumbnail
  4018. // Origin:        PictureViewer
  4019. //
  4020. // Description:    Creates a 64x64 pixel thumbnail of the picture in an
  4021. //                offscreen GWorld pixel map.
  4022. //------------------------------------------------------------------------------
  4023. SOM_Scope    void
  4024. SOMLINK        PictureViewer__GenerateThumbnail
  4025.              (
  4026.                 SampleCode_PictureViewer*        somSelf,
  4027.                 Environment*                    ev,
  4028.                 ODFrame*                        frame
  4029.             )
  4030. {
  4031.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  4032.     SampleCode_PictureViewerMethodDebug("PictureViewer","GenerateThumbnail");
  4033.  
  4034.     SOM_TRY
  4035.         // As this is a Viewer, we know the content can't change. Thus, it
  4036.         // is sufficient to create the thumbnail representation once.
  4037.         if ( _fGWorld == kODNULL )
  4038.         {
  4039.             GDHandle    saveGDevice;
  4040.             CGrafPtr    savePort;
  4041.             Rect        bounds;
  4042.             
  4043.             // Call our utility routine to create the offscreen GWorld.
  4044.             _fGWorld = BeginGWorldThumbnail(&savePort, &saveGDevice);
  4045.     
  4046.             // Ideally, we want to preserve the picture's aspect ratios.
  4047.             // We are not doing that at this time.
  4048.     
  4049.             if ( _fGWorld != kODNULL )
  4050.             {                
  4051.                 SetRect(&bounds, 0, 0, kODThumbnailSize, kODThumbnailSize);
  4052.     
  4053.                 // Draw the picture to the offscreen pixel image
  4054.                 LockPixels( GetGWorldPixMap((GWorldPtr)_fGWorld) );
  4055.                 DrawPicture((PicHandle)_fPicture, &bounds);
  4056.                 UnlockPixels( GetGWorldPixMap((GWorldPtr)_fGWorld) );
  4057.                 
  4058.                 // Done creating our offscreen picture.
  4059.                 EndGWorldThumbnail(savePort, saveGDevice);
  4060.             }
  4061.             else
  4062.                 // We were unable to create out gWorld.
  4063.                 THROW_IF_ERROR(kODErrOutOfMemory);
  4064.         }
  4065.     SOM_CATCH_ALL
  4066.         // If an error occurred, fall back to our default view type.
  4067.         frame->ChangeViewType(ev, gGlobals->fFrameView);
  4068.     SOM_ENDTRY
  4069. }
  4070.  
  4071. //------------------------------------------------------------------------------
  4072. // Method:        GetActiveFacetForFrame
  4073. // Origin:        PictureViewer
  4074. //
  4075. // Description:    This method is called by the part when it needs to know what
  4076. //                the current active facet is.
  4077. //
  4078. //                The part uses this method specifically to find the
  4079. //                facet of a source frame when opening a part window.
  4080. //------------------------------------------------------------------------------
  4081. SOM_Scope    ODFacet*
  4082. SOMLINK        PictureViewer__GetActiveFacetForFrame
  4083.              (
  4084.                 SampleCode_PictureViewer*    somSelf,
  4085.                 Environment*                ev,
  4086.                 ODFrame*                    frame
  4087.             )
  4088. {
  4089.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  4090.     SampleCode_PictureViewerMethodDebug("PictureViewer","GetActiveFacetForFrame");
  4091.  
  4092.     ODFacet*        facet = kODNULL;
  4093.     CFrameInfo*        frameInfo;
  4094.  
  4095.     ODVolatile(facet);
  4096.     
  4097.     SOM_TRY
  4098.         frameInfo = (CFrameInfo*)frame->GetPartInfo(ev);
  4099.         
  4100.         // If the frame is active, and it should be, get the active facet
  4101.         // from the frame state info.
  4102.         if ( frameInfo->IsFrameActive() )
  4103.         {
  4104.             facet = frameInfo->GetActiveFacet();
  4105.         }
  4106.         else
  4107.         {
  4108.             // Otherwise, iterate over the display frames looking for one
  4109.             // that has an active facet... there should be at least one.
  4110.                 
  4111.             TempODFrameFacetIterator fiter(ev, frame);
  4112.             for ( ODFacet* selectedFacet = fiter.First();
  4113.                          fiter.IsNotComplete();
  4114.                          selectedFacet = fiter.Next() )
  4115.             {
  4116.                 if ( selectedFacet->IsSelected(ev) )
  4117.                 {
  4118.                     facet = selectedFacet;
  4119.                     break;        // found it; stop iteration
  4120.                 }
  4121.             }
  4122.         }
  4123.         
  4124.         // If there are no active facets anywhere, this method should never
  4125.         // have been called, so signal an error.
  4126.         if ( facet == kODNULL )
  4127.             THROW(kODErrInvalidFrame);
  4128.     SOM_CATCH_ALL
  4129.     SOM_ENDTRY
  4130.  
  4131.     return facet;
  4132. }
  4133.  
  4134. //------------------------------------------------------------------------------
  4135. // Method:        GeometryChanged
  4136. // Origin:        ODPart
  4137. //
  4138. // Description:    This method is called when the ExternalTransform or
  4139. //                ClipShape of a facet on one of this part's display
  4140. //                frames changes.
  4141. //------------------------------------------------------------------------------
  4142. SOM_Scope void
  4143. SOMLINK PictureViewer__GeometryChanged
  4144.         (
  4145.             SampleCode_PictureViewer*        somSelf, Environment *ev,
  4146.             ODFacet*                         facet,
  4147.             ODBoolean                        clipShapeChanged,
  4148.             ODBoolean                        externalTransformChanged
  4149.         )
  4150. {
  4151.     SampleCode_PictureViewerMethodDebug("PictureViewer","GeometryChanged");
  4152.  
  4153.     SOM_TRY
  4154.         if ( clipShapeChanged )
  4155.             // Specifying kODNULL means to invalidate the clipShape (which was
  4156.             // calculated from the usedShape).
  4157.             facet->Invalidate(ev, kODNULL, kODNULL);
  4158.     SOM_CATCH_ALL
  4159.     SOM_ENDTRY
  4160. }
  4161.  
  4162. //------------------------------------------------------------------------------
  4163. // Method:        FulfillPromise
  4164. // Origin:        ODPart
  4165. //
  4166. // Description:    Fulfill a previously made promise by providing the actual data
  4167. //                the promise represents. The promiseSUView is a view into the same
  4168. //                storage unit value created by SetPromiseValue. The information about
  4169. //                the promise is encoded in the promiseSUView in the part handler's own
  4170. //                internal format. The promise data is written into the promiseSUView,
  4171. //                replacing the data stored in the part handler's format. When the promise
  4172. //                was made, a record of it was kept by this part. The promiseSUView contains
  4173. //                the part's information for that promise. The part uses the data in the
  4174. //                promiseSUView to determine which data to move/copy. The part then writes
  4175. //                the data into the promiseSUView.
  4176. //------------------------------------------------------------------------------
  4177. SOM_Scope    void
  4178. SOMLINK        PictureViewer__FulfillPromise
  4179.             (
  4180.                 SampleCode_PictureViewer*        somSelf,
  4181.                 Environment*                    ev,
  4182.                 ODStorageUnitView*                promiseSUView
  4183.             )
  4184. {
  4185.     SampleCode_PictureViewerData *somThis = SampleCode_PictureViewerGetData(somSelf);
  4186.     SampleCode_PictureViewerMethodDebug("PictureViewer","FulfillPromise");
  4187.  
  4188.     SOM_TRY
  4189.         // We are being asked to provide the data we promised in a previous
  4190.         // clipboard operation. We need to write out the actual data into the
  4191.         // value that we promised before.
  4192.         ODValue picturePtr = ODLockHandle(_fPicture);
  4193.         StorageUnitViewSetValue(promiseSUView, ev, ODGetHandleSize(_fPicture), picturePtr);
  4194.         ODUnlockHandle(_fPicture);
  4195.     SOM_CATCH_ALL
  4196.         ODUnlockHandle(_fPicture);
  4197.     SOM_ENDTRY
  4198. }
  4199.  
  4200. //------------------------------------------------------------------------------
  4201. // Method:        GetPrintResolution
  4202. // Origin:        ODPart
  4203. //
  4204. // Description:    Return the minimum print resolution, represented in dots per
  4205. //                inch, required to print the content of the specified
  4206. //                display frame.
  4207. //------------------------------------------------------------------------------
  4208. SOM_Scope    ODULong
  4209. SOMLINK        PictureViewer__GetPrintResolution
  4210.             (
  4211.                 SampleCode_PictureViewer*    somSelf,
  4212.                 Environment*                ev, 
  4213.                 ODFrame*                     /*frame*/
  4214.             )
  4215. {
  4216.     SampleCode_PictureViewerMethodDebug("PictureViewer","GetPrintResolution");
  4217.  
  4218.     return kMinImagingResolution;
  4219. }
  4220.  
  4221.  
  4222. //=======================================================================
  4223. //
  4224. // Unimplemented Methods • Unimplemented Methods • Unimplemented Methods
  4225. //
  4226. //=======================================================================
  4227.  
  4228. //------------------------------------------------------------------------------
  4229. // Method:        AcquireExtension
  4230. // Origin:        ODObject
  4231. //------------------------------------------------------------------------------
  4232. SOM_Scope    ODExtension*
  4233. SOMLINK     PictureViewer__AcquireExtension(SampleCode_PictureViewer *somSelf,
  4234.                                             Environment *ev, ODType extensionName)
  4235. {
  4236.     SampleCode_PictureViewerMethodDebug("PictureViewer","AcquireExtension");
  4237.  
  4238.     ODExtension* result;
  4239.  
  4240.     SOM_TRY
  4241.         // We don't support any extensions, but one of our parent classes might;
  4242.         result = SampleCode_PictureViewer_parent_ODPart_AcquireExtension(somSelf,ev,extensionName);
  4243.     SOM_CATCH_ALL
  4244.         result = kODNULL;
  4245.     SOM_ENDTRY
  4246.  
  4247.     return result;
  4248. }
  4249.  
  4250. //------------------------------------------------------------------------------
  4251. // Method:        HasExtension
  4252. // Origin:        ODObject
  4253. //------------------------------------------------------------------------------
  4254. SOM_Scope ODBoolean
  4255. SOMLINK     PictureViewer__HasExtension(SampleCode_PictureViewer *somSelf,
  4256.                                         Environment *ev, ODType extensionName)
  4257. {
  4258.     SampleCode_PictureViewerMethodDebug("PictureViewer","HasExtension");
  4259.  
  4260.     ODBoolean result;
  4261.  
  4262.     SOM_TRY
  4263.         // We don't support any extensions, but one of our parent classes might;
  4264.         result = SampleCode_PictureViewer_parent_ODPart_HasExtension(somSelf,ev,extensionName);
  4265.     SOM_CATCH_ALL
  4266.         result = kODFalse;
  4267.     SOM_ENDTRY
  4268.  
  4269.     return result;
  4270. }
  4271.  
  4272. //------------------------------------------------------------------------------
  4273. // Method:        ReleaseExtension
  4274. // Origin:        ODObject
  4275. //------------------------------------------------------------------------------
  4276. SOM_Scope void
  4277. SOMLINK PictureViewer__ReleaseExtension(SampleCode_PictureViewer *somSelf,
  4278.                                         Environment *ev, ODExtension* extension)
  4279. {
  4280.     SampleCode_PictureViewerMethodDebug("PictureViewer","ReleaseExtension");
  4281.  
  4282.     SOM_TRY
  4283.         // We don't support any extensions, but one of our parent classes might;
  4284.         SampleCode_PictureViewer_parent_ODPart_ReleaseExtension(somSelf,ev,extension);
  4285.     SOM_CATCH_ALL
  4286.     SOM_ENDTRY
  4287. }
  4288.  
  4289. //------------------------------------------------------------------------------
  4290. // Method:        HighlightChanged
  4291. // Origin:        ODPart
  4292. //------------------------------------------------------------------------------
  4293. SOM_Scope    void
  4294. SOMLINK        PictureViewer__HighlightChanged(SampleCode_PictureViewer*    somSelf,
  4295.                                             Environment* ev, ODFacet* /*facet*/)
  4296. {
  4297.     SampleCode_PictureViewerMethodDebug("PictureViewer","HighlightChanged");
  4298. }
  4299.  
  4300.  
  4301.  
  4302. //------------------------------------------------------------------------------
  4303. // Method:        ContainingPartPropertiesUpdated
  4304. // Origin:        ODPart
  4305. //------------------------------------------------------------------------------
  4306. SOM_Scope    void
  4307. SOMLINK        PictureViewer__ContainingPartPropertiesUpdated(SampleCode_PictureViewer *somSelf,
  4308.                                     Environment *ev, ODFrame* /*frame*/, ODStorageUnit* /*propertyUnit*/)
  4309. {
  4310.     SampleCode_PictureViewerMethodDebug("PictureViewer","ContainingPartPropertiesUpdated");
  4311. }
  4312.  
  4313. //------------------------------------------------------------------------------
  4314. // Method:        PresentationChanged
  4315. // Origin:        ODPart
  4316. //------------------------------------------------------------------------------
  4317. SOM_Scope    void
  4318. SOMLINK        PictureViewer__PresentationChanged(SampleCode_PictureViewer *somSelf,
  4319.                                                 Environment *ev, ODFrame* /*frame*/)
  4320. {
  4321.     SampleCode_PictureViewerMethodDebug("PictureViewer","PresentationChanged");
  4322. }
  4323.  
  4324. //------------------------------------------------------------------------------
  4325. // Method:        SequenceChanged
  4326. // Origin:        ODPart
  4327. //------------------------------------------------------------------------------
  4328. SOM_Scope    void
  4329. SOMLINK        PictureViewer__SequenceChanged(SampleCode_PictureViewer *somSelf,
  4330.                                         Environment *ev, ODFrame* /*frame*/)
  4331. {
  4332.     SampleCode_PictureViewerMethodDebug("PictureViewer","SequenceChanged");
  4333. }
  4334.  
  4335. //------------------------------------------------------------------------------
  4336. // Method:        CanvasChanged
  4337. // Origin:        ODPart
  4338. //------------------------------------------------------------------------------
  4339. SOM_Scope    void
  4340. SOMLINK        PictureViewer__CanvasChanged(SampleCode_PictureViewer* somSelf,
  4341.                                             Environment* ev, ODFacet* /*facet*/)
  4342. {
  4343.     SampleCode_PictureViewerMethodDebug("PictureViewer","CanvasChanged");
  4344. }
  4345.  
  4346. //------------------------------------------------------------------------------
  4347. // Method:        CanvasUpdated
  4348. // Origin:        ODPart
  4349. //------------------------------------------------------------------------------
  4350. SOM_Scope    void
  4351. SOMLINK        PictureViewer__CanvasUpdated(SampleCode_PictureViewer *somSelf, Environment *ev,
  4352.                                 ODCanvas* /*canvas*/)
  4353. {
  4354.     SampleCode_PictureViewerMethodDebug("PictureViewer","CanvasUpdated");
  4355. }
  4356.  
  4357. //------------------------------------------------------------------------------
  4358. // Method:        LinkStatusChanged
  4359. // Origin:        ODPart
  4360. //------------------------------------------------------------------------------
  4361. SOM_Scope    void
  4362. SOMLINK        PictureViewer__LinkStatusChanged(SampleCode_PictureViewer *somSelf,
  4363.                                             Environment *ev, ODFrame* /*frame*/)
  4364. {
  4365.     SampleCode_PictureViewerMethodDebug("PictureViewer","LinkStatusChanged");
  4366. }
  4367.